<commit_before>const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;

const ArrayView = imports.ArrayView;
const TextView = imports.TextView;
const OMeta = imports.standalone;
const Structure = imports.StructureMapper;

//
let loadFile = function(path) {
  let file = Gio.File.new_for_path(path);
  let [, source] = file.load_contents(null);
  return '' + source;
};

const OMetaMap = JSON.parse(loadFile('standalone.js.map'));

let _ometaFiles = {};
let ometaCode = function(filename, start, stop) {
  if (!_ometaFiles[filename]) {
    _ometaFiles[filename] = loadFile('../' + filename);
  }
  return _ometaFiles[filename].slice(start, stop).trim();
};

let ometaLabel = function(id) {
  let sitem = OMetaMap.map[id];
  return ometaCode(OMetaMap.filenames[sitem[0]], sitem[1], sitem[2]);
};

//
Gtk.init(null, null);

let paned = new Gtk.Paned();

let scrolled = new Gtk.ScrolledWindow();
let textview = new TextView.TextView();
scrolled.add(textview.getWidget());
paned.add1(scrolled);

let popover = new Gtk.Popover({
  position: Gtk.PositionType.BOTTOM,
  relative_to: textview.getWidget(),
});
popover.set_size_request(350, 200);
scrolled = new Gtk.ScrolledWindow();
let popoverview = new ArrayView.ArrayView();
popoverview.setDataController({
  getModel: function() {
    return [{ type: GObject.TYPE_STRING, renderer: 'text' }];
  },
  render: function(parent, data) {
    for (let i = 0; i < data.length; i++) {
      let item = data[i];
      if (item.id >= 0) {
        let iter = this.insertBefore(parent, null);
        this.set(iter, item, [ometaLabel(item.id)]);
      }
    }
  },
});
scrolled.add(popoverview.getWidget());
popover.add(scrolled);

scrolled = new Gtk.ScrolledWindow();
let structview = new ArrayView.ArrayView();
structview.setDataController({
  getModel: function() {
    return [{ type: GObject.TYPE_STRING, renderer: 'text' },
            { type: GObject.TYPE_INT, renderer: 'text' },
            { type: GObject.TYPE_INT, renderer: 'text' } ];
  },
  render: function(parent, data) {
    let iter = this.insertBefore(parent, null);
    this.set(iter, data, [data.id >= 0 ? ometaLabel(data.id) : "",
                          data.start.idx, data.stop.idx]);
    for (let i = 0; i < data.children.length; i++)
      this.render(iter, data.children[i]);
  },
});

scrolled.add(structview.getWidget());
paned.add2(scrolled);

//
let _structure = null;
let findMatchingStructureChild = function(parent, offset) {
  for (let i = 0; i < parent.children.length; i++) {
    let child = parent.children[i];
    if (child.start.idx <= offset && child.stop.idx >= offset)
      return child;
  }
  return null;
};
let getMatchStructure = function(offset) {
  let matches = [], child = _structure;
  let iter = 0;
  do {
    matches.unshift(child);
    child = findMatchingStructureChild(child, offset);
    iter++;
  } while (child);
  return matches;
};

//
textview.onChange(function(text) {
  OMeta.BSOMetaJSParser.matchAll(text, "topLevel", undefined, function(err, tree, value) {
    if (err) {
      log('Parsing: ' + err);
      return;
    }

    _structure = tree;
    structview.setData(_structure);
  });
}.bind(this));

textview.getWidget().connect('motion-notify-event', function(widget, event) {
  if ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) == 0)
    return false;
  if (!_structure)
    return false;

  let [, x, y] = event.get_coords();
  let offset = textview.getOffsetAtLocation(x, y),
      matches = getMatchStructure(offset),
      match = matches[0];
  textview.hightlightRange(match.start.idx, match.stop.idx);
  //log('offset=' + offset + ' match=' + match.title + ' range=' + match.start + ',' + match.stop);

  return false;
}.bind(this));

let positionPopover = function(popover, parent, x, y) {
  let allocation = parent.get_allocation();
  let rect = popover.pointing_to;
  rect.x = x + allocation.x;
  rect.y = y + allocation.y;
  popover.pointing_to = rect;
};

textview.getWidget().connect('button-release-event', function(widget, event) {
  if ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) == 0)
    return false;
  if (!_structure)
    return false;

  let [, x, y] = event.get_coords();
  let offset = textview.getOffsetAtLocation(x, y),
      matches = getMatchStructure(offset),
      match = matches[0];
  textview.hightlightRange(match.start.idx, match.stop.idx);

  let rect = textview.getRectForRange(match.start.idx, match.stop.idx);
  positionPopover(popover, widget,
                  rect.x + rect.width / 2,
                  rect.y + rect.height);
  popoverview.setData(matches);
  popover.show_all();

  return true;
}.bind(this));
textview.getWidget().connect('button-release-event', function(widget, event) {
  if ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) == 0)
    popover.hide();
  return false;
}.bind(this));

//
structview.onChange(function(value) {
  textview.hightlightRange(value.start.idx, value.stop.idx);
}.bind(this));
popoverview.onChange(function(value) {
  textview.hightlightRange(value.start.idx, value.stop.idx);
}.bind(this));

//
let file = Gio.File.new_for_path('./lr.ometajs');
let [, data] = file.load_contents(null);
let source = '' + data;
textview.setData(source);

//
let win = new Gtk.Window();
win.connect('destroy', (function() { Gtk.main_quit(); }).bind(this));

win.resize(800, 400);
paned.position = 800 / 2;
win.add(paned);
win.show_all();

Gtk.main();
<commit_msg>ui: fix popover placement when scrolling<commit_after>const GObject = imports.gi.GObject;
const Gio = imports.gi.Gio;
const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;

const ArrayView = imports.ArrayView;
const TextView = imports.TextView;
const OMeta = imports.standalone;
const Structure = imports.StructureMapper;

//
let loadFile = function(path) {
  let file = Gio.File.new_for_path(path);
  let [, source] = file.load_contents(null);
  return '' + source;
};

const OMetaMap = JSON.parse(loadFile('standalone.js.map'));

let _ometaFiles = {};
let ometaCode = function(filename, start, stop) {
  if (!_ometaFiles[filename]) {
    _ometaFiles[filename] = loadFile('../' + filename);
  }
  return _ometaFiles[filename].slice(start, stop).trim();
};

let ometaLabel = function(id) {
  let sitem = OMetaMap.map[id];
  return ometaCode(OMetaMap.filenames[sitem[0]], sitem[1], sitem[2]);
};

//
Gtk.init(null, null);

let paned = new Gtk.Paned();

let scrolled = new Gtk.ScrolledWindow();
let textview = new TextView.TextView();
scrolled.add(textview.getWidget());
paned.add1(scrolled);

let popover = new Gtk.Popover({
  position: Gtk.PositionType.BOTTOM,
  relative_to: textview.getWidget(),
});
popover.set_size_request(350, 200);
scrolled = new Gtk.ScrolledWindow();
let popoverview = new ArrayView.ArrayView();
popoverview.setDataController({
  getModel: function() {
    return [{ type: GObject.TYPE_STRING, renderer: 'text' }];
  },
  render: function(parent, data) {
    for (let i = 0; i < data.length; i++) {
      let item = data[i];
      if (item.id >= 0) {
        let iter = this.insertBefore(parent, null);
        this.set(iter, item, [ometaLabel(item.id)]);
      }
    }
  },
});
scrolled.add(popoverview.getWidget());
popover.add(scrolled);

scrolled = new Gtk.ScrolledWindow();
let structview = new ArrayView.ArrayView();
structview.setDataController({
  getModel: function() {
    return [{ type: GObject.TYPE_STRING, renderer: 'text' },
            { type: GObject.TYPE_INT, renderer: 'text' },
            { type: GObject.TYPE_INT, renderer: 'text' } ];
  },
  render: function(parent, data) {
    let iter = this.insertBefore(parent, null);
    this.set(iter, data, [data.id >= 0 ? ometaLabel(data.id) : "",
                          data.start.idx, data.stop.idx]);
    for (let i = 0; i < data.children.length; i++)
      this.render(iter, data.children[i]);
  },
});

scrolled.add(structview.getWidget());
paned.add2(scrolled);

//
let _structure = null;
let findMatchingStructureChild = function(parent, offset) {
  for (let i = 0; i < parent.children.length; i++) {
    let child = parent.children[i];
    if (child.start.idx <= offset && child.stop.idx >= offset)
      return child;
  }
  return null;
};
let getMatchStructure = function(offset) {
  let matches = [], child = _structure;
  let iter = 0;
  do {
    matches.unshift(child);
    child = findMatchingStructureChild(child, offset);
    iter++;
  } while (child);
  return matches;
};

//
textview.onChange(function(text) {
  OMeta.BSOMetaJSParser.matchAll(text, "topLevel", undefined, function(err, tree, value) {
    if (err) {
      log('Parsing: ' + err);
      return;
    }

    _structure = tree;
    structview.setData(_structure);
  });
}.bind(this));

textview.getWidget().connect('motion-notify-event', function(widget, event) {
  if ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) == 0)
    return false;
  if (!_structure)
    return false;

  let [, x, y] = event.get_coords();
  let offset = textview.getOffsetAtLocation(x, y),
      matches = getMatchStructure(offset),
      match = matches[0];
  textview.hightlightRange(match.start.idx, match.stop.idx);
  //log('offset=' + offset + ' match=' + match.title + ' range=' + match.start + ',' + match.stop);

  return false;
}.bind(this));

let positionPopover = function(popover, parent, x, y) {
  let allocation = parent.get_allocation();
  let rect = popover.pointing_to;
  rect.x = x + allocation.x - parent.hadjustment.value;
  rect.y = y + allocation.y - parent.vadjustment.value;
  popover.pointing_to = rect;
};

textview.getWidget().connect('button-release-event', function(widget, event) {
  if ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) == 0)
    return false;
  if (!_structure)
    return false;

  let [, x, y] = event.get_coords();
  let offset = textview.getOffsetAtLocation(x, y),
      matches = getMatchStructure(offset),
      match = matches[0];
  textview.hightlightRange(match.start.idx, match.stop.idx);

  let rect = textview.getRectForRange(match.start.idx, match.stop.idx);
  positionPopover(popover, widget,
                  rect.x + rect.width / 2,
                  rect.y + rect.height);
  popoverview.setData(matches);
  popover.show_all();

  return true;
}.bind(this));
textview.getWidget().connect('button-release-event', function(widget, event) {
  if ((event.get_state()[1] & Gdk.ModifierType.CONTROL_MASK) == 0)
    popover.hide();
  return false;
}.bind(this));

//
structview.onChange(function(value) {
  textview.hightlightRange(value.start.idx, value.stop.idx);
}.bind(this));
popoverview.onChange(function(value) {
  textview.hightlightRange(value.start.idx, value.stop.idx);
}.bind(this));

//
let file = Gio.File.new_for_path('./lr.ometajs');
let [, data] = file.load_contents(null);
let source = '' + data;
textview.setData(source);

//
let win = new Gtk.Window();
win.connect('destroy', (function() { Gtk.main_quit(); }).bind(this));

win.resize(800, 400);
paned.position = 800 / 2;
win.add(paned);
win.show_all();

Gtk.main();
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var DEAD = 0;
var LIVE = 1;

var sampleInput = "4 8\n........\n....*...\n...**...\n........\n";

var Game = function(r,c) {
  var game = {
      rows: r,
      cols: c,
      neighbours: function(c,r) {
        var n = 0;
        for (var i=-1;i<=1;++i) {
          for (var j=-1;j<=1;++j) {
            if (i === 0 && j === 0) {
              continue;
            }

            if (this[c+j] && this[c+j][r+i] === LIVE) {
              ++n;
            }
          }
        }
        return n;
      },
      to_string: function() {
        var s = this.rows + ' ' + this.cols + '\n';
        for (var i=0;i<this.rows;++i) {
          for (var j=0;j<this.cols;++j) {
            s+= (this[j][i] === LIVE ? '*' : '.');
          }
          s+='\n';
        }
        return s;
      }
  };
  return game;
};

var createGrid = function(s) {
  var lines = s.split('\n');
  var rc = lines[0].split(' ');
  var rows = rc[0] | 0; // 4
  var cols = rc[1] | 0; // 8

  var game = new Game(rows,cols);

  for (var i=0;i<rows;++i) {
    for (var j=0;j<cols;++j) {
      var v = lines[1+i][j];
      if (game[j] === undefined) { game[j] = []; }
      game[j][i] = v === '*' ? LIVE : DEAD;
    }
  }

  return game;
};

var cellState = function(state,neighbours) {
  if (neighbours < 2 && state === LIVE) {
    return DEAD;
  }
  else if (neighbours > 3 && state === LIVE) {
    return DEAD;
  }
  else if ((neighbours === 2 || neighbours === 3) && state === LIVE) {
    return LIVE;
  }
  else if (neighbours === 3 && state === DEAD) {
    return LIVE;
  }
  else {
    return DEAD;
  }
};

describe('game of life', function() {
  describe('cell', function() {
    it('dies with underpopulation', function() {
      assert.equal(DEAD, cellState(LIVE,1));
    });

    it('dies with overcrowding', function() {
      assert.equal(DEAD, cellState(LIVE,4));
    });

    it('maintains live if 2 or three neighbours', function() {
      assert.equal(LIVE, cellState(LIVE,2));
      assert.equal(LIVE, cellState(LIVE,3));
    });

    it('becomes alive', function() {
      assert.equal(LIVE, cellState(DEAD,3));
    });

    it('is fully defined', function() {
      for (var i=0;i<=8;++i) {
        assert(undefined !== cellState(DEAD,i));
        assert(undefined !== cellState(LIVE,i));
      }
    });
  });

  describe('grid', function() {
    it('should read input', function() {
      var grid = createGrid(sampleInput);

      assert.equal(4, grid.rows);

      assert.equal(DEAD, grid[0][0]);
      assert.equal(LIVE, grid[4][1]);
      assert.equal(LIVE, grid[3][2]);
      assert.equal(LIVE, grid[4][2]);
    });

    it('should be able to get the number of live neighbours', function() {
      var grid = createGrid(sampleInput);

      assert.equal(0, grid.neighbours(0,0));
      assert.equal(2, grid.neighbours(3,2));

      grid = createGrid('2 2\n..\n..');
      assert.equal(0, grid.neighbours(0,0));
      assert.equal(0, grid.neighbours(1,0));
      assert.equal(0, grid.neighbours(0,1));
      assert.equal(0, grid.neighbours(1,1));

      grid = createGrid('2 2\n**\n**');
      assert.equal(3, grid.neighbours(0,0));
      assert.equal(3, grid.neighbours(1,0));
      assert.equal(3, grid.neighbours(0,1));
      assert.equal(3, grid.neighbours(1,1));
    });

    it('should have a sensible printed representation', function() {
      var grid = createGrid('1 1\n.');
      assert.equal('1 1\n.\n', grid.to_string());
    });
  });
});

<commit_msg>woo, roundtripped works<commit_after>"use strict";

var assert = require('assert');

var DEAD = 0;
var LIVE = 1;

var sampleInput = "4 8\n........\n....*...\n...**...\n........\n";

var Game = function(r,c) {
  var game = {
      rows: r,
      cols: c,
      neighbours: function(c,r) {
        var n = 0;
        for (var i=-1;i<=1;++i) {
          for (var j=-1;j<=1;++j) {
            if (i === 0 && j === 0) {
              continue;
            }

            if (this[c+j] && this[c+j][r+i] === LIVE) {
              ++n;
            }
          }
        }
        return n;
      },
      to_string: function() {
        var s = this.rows + ' ' + this.cols + '\n';
        for (var i=0;i<this.rows;++i) {
          for (var j=0;j<this.cols;++j) {
            s+= (this[j][i] === LIVE ? '*' : '.');
          }
          s+='\n';
        }
        return s;
      }
  };
  return game;
};

var createGrid = function(s) {
  var lines = s.split('\n');
  var rc = lines[0].split(' ');
  var rows = rc[0] | 0; // 4
  var cols = rc[1] | 0; // 8

  var game = new Game(rows,cols);

  for (var i=0;i<rows;++i) {
    for (var j=0;j<cols;++j) {
      var v = lines[1+i][j];
      if (game[j] === undefined) { game[j] = []; }
      game[j][i] = v === '*' ? LIVE : DEAD;
    }
  }

  return game;
};

var cellState = function(state,neighbours) {
  if (neighbours < 2 && state === LIVE) {
    return DEAD;
  }
  else if (neighbours > 3 && state === LIVE) {
    return DEAD;
  }
  else if ((neighbours === 2 || neighbours === 3) && state === LIVE) {
    return LIVE;
  }
  else if (neighbours === 3 && state === DEAD) {
    return LIVE;
  }
  else {
    return DEAD;
  }
};

describe('game of life', function() {
  describe('cell', function() {
    it('dies with underpopulation', function() {
      assert.equal(DEAD, cellState(LIVE,1));
    });

    it('dies with overcrowding', function() {
      assert.equal(DEAD, cellState(LIVE,4));
    });

    it('maintains live if 2 or three neighbours', function() {
      assert.equal(LIVE, cellState(LIVE,2));
      assert.equal(LIVE, cellState(LIVE,3));
    });

    it('becomes alive', function() {
      assert.equal(LIVE, cellState(DEAD,3));
    });

    it('is fully defined', function() {
      for (var i=0;i<=8;++i) {
        assert(undefined !== cellState(DEAD,i));
        assert(undefined !== cellState(LIVE,i));
      }
    });
  });

  describe('grid', function() {
    it('should read input', function() {
      var grid = createGrid(sampleInput);

      assert.equal(4, grid.rows);

      assert.equal(DEAD, grid[0][0]);
      assert.equal(LIVE, grid[4][1]);
      assert.equal(LIVE, grid[3][2]);
      assert.equal(LIVE, grid[4][2]);
    });

    it('should be able to get the number of live neighbours', function() {
      var grid = createGrid(sampleInput);

      assert.equal(0, grid.neighbours(0,0));
      assert.equal(2, grid.neighbours(3,2));

      grid = createGrid('2 2\n..\n..');
      assert.equal(0, grid.neighbours(0,0));
      assert.equal(0, grid.neighbours(1,0));
      assert.equal(0, grid.neighbours(0,1));
      assert.equal(0, grid.neighbours(1,1));

      grid = createGrid('2 2\n**\n**');
      assert.equal(3, grid.neighbours(0,0));
      assert.equal(3, grid.neighbours(1,0));
      assert.equal(3, grid.neighbours(0,1));
      assert.equal(3, grid.neighbours(1,1));
    });

    it('should have a sensible printed representation', function() {
      var grid = createGrid('1 1\n.');
      assert.equal('1 1\n.\n', grid.to_string());

      grid = createGrid(sampleInput);
      assert.equal(sampleInput, grid.to_string());
    });
  });
});

<|endoftext|>


<commit_before>var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace = /^\s+/,
	rsingleTag = /^<(\w+)\s*\/?>$/,
	rxhtmlTag = /(<(\w+)[^>]*?)\/>/g,
	rselfClosing = /^(?:abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i,
	rinsideTable = /^<(thead|tbody|tfoot|colg|cap)/,
	rtbody = /
</" + tag + ">";
	};

jQuery.fn.extend({
	text: function( text ) {
		if ( typeof text !== "object" && text !== undefined )
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

		var ret = "";

		jQuery.each( text || this, function(){
			jQuery.each( this.childNodes, function(){
				if ( this.nodeType !== 8 ) {
					ret += this.nodeType !== 1 ?
						this.nodeValue :
						jQuery.fn.text( [ this ] );
				}
			});
		});

		return ret;
	},

	wrapAll: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function() {
				jQuery(this).wrapAll( html.apply(this, arguments) );
			});
		}

		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone();

			if ( this[0].parentNode ) {
				wrap.insertBefore( this[0] );
			}

			wrap.map(function(){
				var elem = this;

				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
					elem = elem.firstChild;
				}

				return elem;
			}).append(this);
		}

		return this;
	},

	wrapInner: function( html ) {
		return this.each(function(){
			jQuery( this ).contents().wrapAll( html );
		});
	},

	wrap: function( html ) {
		return this.each(function(){
			jQuery( this ).wrapAll( html );
		});
	},

	append: function() {
		return this.domManip(arguments, true, function(elem){
			if ( this.nodeType === 1 ) {
				this.appendChild( elem );
			}
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, function(elem){
			if ( this.nodeType === 1 ) {
				this.insertBefore( elem, this.firstChild );
			}
		});
	},

	before: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this );
		});
	},

	after: function() {
		return this.domManip(arguments, false, function(elem){
			this.parentNode.insertBefore( elem, this.nextSibling );
		});
	},

	clone: function( events ) {
		// Do the clone
		var ret = this.map(function(){
			if ( !jQuery.support.noCloneEvent && !jQuery.isXMLDoc(this) ) {
				// IE copies events bound via attachEvent when
				// using cloneNode. Calling detachEvent on the
				// clone will also remove the events from the orignal
				// In order to get around this, we use innerHTML.
				// Unfortunately, this means some modifications to
				// attributes in IE that are actually only stored
				// as properties will not be copied (such as the
				// the name attribute on an input).
				var html = this.outerHTML, ownerDocument = this.ownerDocument;
				if ( !html ) {
					var div = ownerDocument.createElement("div");
					div.appendChild( this.cloneNode(true) );
					html = div.innerHTML;
				}

				return jQuery.clean([html.replace(rinlinejQuery, "")
					.replace(rleadingWhitespace, "")], ownerDocument)[0];
			} else {
				return this.cloneNode(true);
			}
		});

		// Copy the events from the original to the clone
		if ( events === true ) {
			var orig = this.find("*").andSelf(), i = 0;

			ret.find("*").andSelf().each(function(){
				if ( this.nodeName !== orig[i].nodeName ) { return; }

				var events = jQuery.data( orig[i], "events" );

				for ( var type in events ) {
					for ( var handler in events[ type ] ) {
						jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data );
					}
				}

				i++;
			});
		}

		// Return the cloned set
		return ret;
	},

	html: function( value ) {
		return value === undefined ?
			(this[0] ?
				this[0].innerHTML.replace(rinlinejQuery, "") :
				null) :
			this.empty().append( value );
	},

	replaceWith: function( value ) {
		return this.after( value ).remove();
	},

	domManip: function( args, table, callback ) {
		var fragment, scripts, cacheable, cached, cacheresults, first,
			value = args[0];

		if ( jQuery.isFunction(value) ) {
			return this.each(function() {
				args[0] = value.call(this);
				return jQuery(this).domManip( args, table, callback );
			});
		}

		if ( this[0] ) {
			if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && args[0].indexOf("<option") < 0 ) {
				cacheable = true;
				cacheresults = jQuery.fragments[ args[0] ];
				if ( cacheresults ) {
					if ( cacheresults !== 1 ) {
						fragment = cacheresults;
					}
					cached = true;
				}
			}

			if ( !fragment ) {
				fragment = (this[0].ownerDocument || this[0]).createDocumentFragment();
				scripts = jQuery.clean( args, (this[0].ownerDocument || this[0]), fragment );
			}

			first = fragment.firstChild;

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						cacheable || this.length > 1 || i > 0 ?
							fragment.cloneNode(true) :
							fragment
					);
				}
			}

			if ( scripts ) {
				jQuery.each( scripts, evalScript );
			}

			if ( cacheable ) {
				jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
			}
		}

		return this;

		function root( elem, cur ) {
			return jQuery.nodeName(elem, "table") ?
				(elem.getElementsByTagName("tbody")[0] ||
				elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
				elem;
		}
	}
});

jQuery.fragments = {};

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function(name, original){
	jQuery.fn[ name ] = function( selector ) {
		var ret = [], insert = jQuery( selector );

		for ( var i = 0, l = insert.length; i < l; i++ ) {
			var elems = (i > 0 ? this.clone(true) : this).get();
			jQuery.fn[ original ].apply( jQuery(insert[i]), elems );
			ret = ret.concat( elems );
		}

		return this.pushStack( ret, name, selector );
	};
});

jQuery.each({
	// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		if ( !selector || jQuery.multiFilter( selector, [ this ] ).length ) {
			if ( !keepData && this.nodeType === 1 ) {
				cleanData( jQuery("*", this).add(this) );
			}

			this.parentNode && this.parentNode.removeChild( this );
		}
	},

	detach: function( selector ) {
		jQuery( this ).remove( selector, true )
	},

	empty: function() {
		// Remove element nodes and prevent memory leaks
		if ( this.nodeType === 1 ) {
			cleanData( jQuery("*", this) );
		}

		// Remove any remaining nodes
		while ( this.firstChild ) {
			this.removeChild( this.firstChild );
		}
	}
}, function(name, fn){
	jQuery.fn[ name ] = function(){
		return this.each( fn, arguments );
	};
});

jQuery.extend({
	clean: function( elems, context, fragment ) {
		context = context || document;

		// !context.createElement fails in IE with an error but returns typeof 'object'
		if ( typeof context.createElement === "undefined" ) {
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
		}

		// If a single string is passed in and it's a single tag
		// just do a createElement and skip the rest
		if ( !fragment && elems.length === 1 && typeof elems[0] === "string" ) {
			var match = rsingleTag.exec(elems[0]);
			if ( match ) {
				return [ context.createElement( match[1] ) ];
			}
		}

		var ret = [], scripts = [], div = context.createElement("div");

		jQuery.each(elems, function(i, elem){
			if ( typeof elem === "number" ) {
				elem += '';
			}

			if ( !elem ) { return; }

			// Convert html string into DOM nodes
			if ( typeof elem === "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(rxhtmlTag, fcloseTag);

				// Trim whitespace, otherwise indexOf won't work as expected
				var tags = elem.replace(rleadingWhitespace, "")
					.substring(0, 10).toLowerCase();

				var wrap =
					// option or optgroup
					!tags.indexOf("<opt") &&
					[ 1, "<select multiple='multiple'>", "</select>" ] ||

					!tags.indexOf("<leg") &&
					[ 1, "<fieldset>", "</fieldset>" ] ||

					rinsideTable.test(tags) &&
					[ 1, "
", "
" ] ||

					!tags.indexOf("<tr") &&
					[ 2, "

", "

" ] ||

				 	//
 matched above
					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
					[ 3, "

", "

" ] ||

					!tags.indexOf("<col") &&
					[ 2, "

<colgroup>", "</colgroup>
" ] ||

					// IE can't serialize <link> and


<commit_before>var m = require('mithril');
var xhr = require('../studyXhr');
var embedYoutube = require('../studyComments').embedYoutube;
var makeSuccess = require('./studyPracticeSuccess');

var readOnlyProp = function(value) {
  return function() {
    return value;
  };
};

var commentYoutubeRegex = /(?:https?:\/\/)(?:www\.)(?:youtube\.com|youtu\.be)\/(?:watch)?(?:\?v=)?([^"&?\/ ]{11})/gi;

module.exports = function(root, studyData, data) {

  var goal = m.prop();
  var comment = m.prop();
  var nbMoves = m.prop(0);
  var success = m.prop(null); // null = ongoing, true = win, false = fail

  var makeComment = function(treeRoot) {
    if (!treeRoot.comments) return;
    var c = embedYoutube(treeRoot.comments[0].text);
    delete treeRoot.comments;
    return c;
  };

  var onLoad = function() {
    root.vm.showAutoShapes = readOnlyProp(true);
    root.vm.showGauge = readOnlyProp(true);
    root.vm.showComputer = readOnlyProp(true);
    goal(root.data.practiceGoal);
    nbMoves(0);
    success(null);
    comment(makeComment(root.tree.root));
    var chapter = studyData.chapter;
    history.replaceState(null, chapter.name, data.url + '/' + chapter.id);
  };
  onLoad();

  var computeNbMoves = function() {
    var plies = root.vm.node.ply - root.tree.root.ply;
    if (root.bottomColor() !== root.data.player.color) plies--;
    return Math.ceil(plies / 2);
  };

  var checkSuccess = function() {
    if (success() !== null) return;
    nbMoves(computeNbMoves());
    success(makeSuccess(root, goal(), nbMoves()));
    if (success()) onVictory();
  };

  var onVictory = function() {
    var chapterId = root.study.currentChapter().id;
    var former = data.completion[chapterId] || 999;
    if (nbMoves() < former) {
      data.completion[chapterId] = nbMoves();
      xhr.practiceComplete(chapterId, nbMoves());
    }
  };

  return {
    onReload: onLoad,
    onJump: checkSuccess,
    onCeval: checkSuccess,
    data: data,
    goal: goal,
    success: success,
    comment: comment,
    nbMoves: nbMoves,
    nextChapter: function() {
      var chapters = root.study.data.chapters;
      var currentId = root.study.currentChapter().id;
      for (var i in chapters)
        if (chapters[i].id === currentId) return chapters[parseInt(i) + 1];
    },
    reset: function() {
      root.tree.root.children = [];
      root.userJump('');
      root.practice.reset();
      onLoad();
    }
  };
};
<commit_msg>remove unused regex<commit_after>var m = require('mithril');
var xhr = require('../studyXhr');
var embedYoutube = require('../studyComments').embedYoutube;
var makeSuccess = require('./studyPracticeSuccess');

var readOnlyProp = function(value) {
  return function() {
    return value;
  };
};

module.exports = function(root, studyData, data) {

  var goal = m.prop();
  var comment = m.prop();
  var nbMoves = m.prop(0);
  var success = m.prop(null); // null = ongoing, true = win, false = fail

  var makeComment = function(treeRoot) {
    if (!treeRoot.comments) return;
    var c = embedYoutube(treeRoot.comments[0].text);
    delete treeRoot.comments;
    return c;
  };

  var onLoad = function() {
    root.vm.showAutoShapes = readOnlyProp(true);
    root.vm.showGauge = readOnlyProp(true);
    root.vm.showComputer = readOnlyProp(true);
    goal(root.data.practiceGoal);
    nbMoves(0);
    success(null);
    comment(makeComment(root.tree.root));
    var chapter = studyData.chapter;
    history.replaceState(null, chapter.name, data.url + '/' + chapter.id);
  };
  onLoad();

  var computeNbMoves = function() {
    var plies = root.vm.node.ply - root.tree.root.ply;
    if (root.bottomColor() !== root.data.player.color) plies--;
    return Math.ceil(plies / 2);
  };

  var checkSuccess = function() {
    if (success() !== null) return;
    nbMoves(computeNbMoves());
    success(makeSuccess(root, goal(), nbMoves()));
    if (success()) onVictory();
  };

  var onVictory = function() {
    var chapterId = root.study.currentChapter().id;
    var former = data.completion[chapterId] || 999;
    if (nbMoves() < former) {
      data.completion[chapterId] = nbMoves();
      xhr.practiceComplete(chapterId, nbMoves());
    }
  };

  return {
    onReload: onLoad,
    onJump: checkSuccess,
    onCeval: checkSuccess,
    data: data,
    goal: goal,
    success: success,
    comment: comment,
    nbMoves: nbMoves,
    nextChapter: function() {
      var chapters = root.study.data.chapters;
      var currentId = root.study.currentChapter().id;
      for (var i in chapters)
        if (chapters[i].id === currentId) return chapters[parseInt(i) + 1];
    },
    reset: function() {
      root.tree.root.children = [];
      root.userJump('');
      root.practice.reset();
      onLoad();
    }
  };
};
<|endoftext|>


<commit_before>// CalendarView
// Author:  R. M. Salter
var db = require('lib/db');
var screenWidth = Ti.Platform.displayCaps.platformWidth;
var util = require('lib/Util');

// exported function CalendarView returns a new monthly view
// dis_date is the date whose year and month are to be displayed; sel_date is currently selected JS date
// _cb is a callback function that is invoked on the new selected JS date when one is selected

function CalendarView(dis_date, sel_date, _cb) {
	// break down display date -- only need month and year
	var dyr = dis_date.getFullYear(), dmo = dis_date.getMonth();
	// break down selected date
	var syr = sel_date.getFullYear(), smo = sel_date.getMonth(), sda = sel_date.getDate();
	// what's today's date?
	today = new Date();
	// break down today
	var tyr = today.getFullYear(), tmo = today.getMonth(), tda = today.getDate();
	var toolBar = makeToolBar(dyr, dmo);
	var cal = calendar(dyr, dmo, syr, smo, sda, tyr, tmo, tda, _cb);
	// Main View of the Month View.
	var self = Ti.UI.createView({layout: 'vertical'});
	self.add(toolBar);
	self.add(cal);

	// if 'up' increment month, 'down' decrement
	self.shiftMonth = function(direction) {
		if (direction == 'up') {
			if (dmo == 11) {
				dyr++;
				dmo = 0;
			} else {
				dmo++;
			}
		} else if (direction == 'down') {
			if (dmo == 0) {
				dyr--;
				dmo = 11;
			} else {
				dmo--;
			}
		}
		toolBar = makeToolBar(dyr, dmo);
		cal = calendar(dyr, dmo, syr, smo, sda, tyr, tmo, tda, _cb);
		self.removeAllChildren();
		self.add(toolBar);
		self.add(cal);
	};

	Ti.API.addEventListener('setCalDate', function(e) {
		if (sameDate(dis_date, e.date) && sameDate(sel_date, e.date)) return;
		sel_date = e.date;
		dis_date = e.date;
		// break down selected date
		var syr = sel_date.getFullYear(), smo = sel_date.getMonth(), sda = sel_date.getDate();
		toolBar = makeToolBar(syr, smo);
		cal = calendar(syr, smo, syr, smo, sda, tyr, tmo, tda, _cb);
		self.removeAllChildren();
		self.add(toolBar);
		self.add(cal);
	});
	return self;
}

// Help function to identify to JS dates that represent the same real date

function sameDate(d0, d1) {
	return d0.getFullYear() == d1.getFullYear()
		&& d0.getMonth() == d1.getMonth()
		&& d0.getDate() == d1.getDate();
}

// Builds the toolbar for a give year and month

function makeToolBar(yr, mo) {
	// Tool Bar
	var toolBar = Ti.UI.createView({
		width : screenWidth,
		height : 50,
		backgroundColor : util.CalendarWindowColor.BACKGROUND_COLOR,
		layout : 'vertical'
	});
	// Tool Bar Title
	var toolBarTitle = Ti.UI.createView({
		top : '3dp',
		width : '322dp',
		height : '24dp'
	});
	// Month Title - Tool Bar
	var monthTitle = Ti.UI.createLabel({
		width : 200,
		height : 24,
		text: monthName[mo]+' '+yr,
		textAlign : 'center',
		color : util.CalendarWindowColor.TEXT_COLOR,
		font : {
			fontSize : 20,
			fontWeight : 'bold'
		}
	});
	toolBarTitle.add(monthTitle);
	// Tool Bar Day
	var toolBarDays = Ti.UI.createView({
		top : 2,
		width : 322,
		height : 22,
		layout : 'horizontal',
		left : 0
	});
	var dayLabel = function(daytxt) {
		return Ti.UI.createLabel({
			left : '0dp',
			height : '20dp',
			text : daytxt,
			width : '46dp',
			textAlign : 'center',
			font : {
				fontSize : 12,
				fontWeight : 'bold'
			},
			color : util.CalendarWindowColor.TEXT_COLOR
		});
	};
	for (var i in dayOfWeek) toolBarDays.add(dayLabel(dayOfWeek[i]));
	// Adding Tool Bar Title View & Tool Bar Days View
	toolBar.add(toolBarTitle);
	toolBar.add(toolBarDays);
	return toolBar;
}

// Builds the calendar for a given year and month (yr and mo)
// syr, smo and sda are the selected year, month and day
// tyr, tmo and tda are today
// _cb is the callback applied to the new selected date when one is selected

var calendar = function(yr, mo, syr, smo, sda, tyr, tmo, tda, _cb) {
	// yr,mo,da are selected day; tyr,tmo,tda are today
	//create main calendar view
	var mainView = Ti.UI.createView({
		layout : 'horizontal',
		width : 322,
		height : 'auto',
		cb : _cb
	});

	// determine the cal data
	var isCurrentMonth = (yr == tyr && mo == tmo);
	var isSelectedMonth = (yr == syr && mo == smo);
	var daysInMonth = 32 - new Date(yr, mo, 32).getDate();
	var dayOfMonthToday = tda;
	var dayOfWeek = new Date(yr, mo, 1).getDay();
	var daysInLastMonth = 32 - new Date(yr, mo-1, 32).getDate();
	var daysInNextMonth = (new Date(yr, mo, daysInMonth).getDay()) - 6;
	//set initial day of week number
	var dayNumber = daysInLastMonth - dayOfWeek + 1;
	//get last month's days
	for ( i = 0; i < dayOfWeek; i++) {
		mainView.add(new dayView({
			day : dayNumber,
			taskcount : db.daycount(new Date(yr, mo, dayNumber)),
			color : '#8e959f',
			current : 'no',
		}));
		dayNumber++;
	};
	// reset day number for current month
	dayNumber = 1;
	//get this month's days
	var oldDay = {};
	for ( i = 0; i < daysInMonth; i++) {
		var newDay = new dayView({
			day : dayNumber,
			taskcount : db.daycount(new Date(yr, mo, dayNumber)),
			color : '#3a4756',
			current : 'yes',
		});
		mainView.add(newDay);
		// if this day is today, show it
		if (isCurrentMonth && tda == dayNumber) {
			newDay.color = 'white';
			newDay.backgroundColor = '#FFFFF000';
			oldDay = newDay;
		}
		// if this day is the chosen day, select it
		if (isSelectedMonth && dayNumber == sda) select(newDay);
	    dayNumber++;
	}
	// reset day number for next month
	dayNumber = 1;
	//get remaining month's days
	for ( i = 0; i > daysInNextMonth; i--) {
		  mainView.add(new dayView({
			 day : dayNumber,
			 taskcount : db.daycount(new Date(yr, mo, dayNumber)),
			 color : '#8e959f',
			 current : 'no',
		  }));
	     dayNumber++;
	 }
	// day selection event listener
	mainView.addEventListener('click', function(e) {
		if (e.source.current == 'yes') {
			select(e.source);
			if (mainView.cb != null) mainView.cb(new Date(yr, mo, e.source.text));
		}
	});
	return mainView;

	// function to highlight selected day
	function select(dayView) {
		if (isCurrentMonth && oldDay.text == dayOfMonthToday) {
			oldDay.color = 'white';
			oldDay.backgroundColor = '#FFFFF000';
		} else {
			oldDay.color = '#3a4756';
			oldDay.backgroundColor = '#FFDCDCDF';
		}
		oldDay.backgroundPaddingLeft = 0;
		oldDay.backgroundPaddingBottom = 0;
		if (isCurrentMonth && dayView.text == dayOfMonthToday) {
			dayView.backgroundColor = '#FFFF00FF';
		} else {
			dayView.backgroundColor = '#FFFF0000';
		}
		dayView.backgroundPaddingLeft = 1;
		dayView.backgroundPaddingBottom = 1;
		dayView.color = 'white';
		oldDay = dayView;
	};
};

// creates a label for a day given an object containing date
// of month and color

function dayView(e) {
	var self = Ti.UI.createView({
		width : '46dp',
		height : '44dp',
		current: e.current,
		color: e.color,
		backgroundColor : util.CalendarWindowColor.BACKGROUND_COLOR,
		borderColor: util.CalendarWindowColor.BORDER_COLOR,
		borderWidth: '1dp'
	});

	var dayLabel = Ti.UI.createLabel({
		text : e.day,
		textAlign : 'center',
		current: e.current,
		font : {
			fontSize : 20,
			fontWeight : 'bold'
		}
	});

	if (e.taskcount) {
		var taskNotifier = Ti.UI.createLabel({
			text: e.taskcount,
			textAlign: 'center',
			right: '2dp',
			top: '2dp',
			backgroundColor: 'orange',
			color: 'black',
			font: {
				fontSize: 9,
				fontWeight: 'bold'
			}
		});
		self.add(taskNotifier);
	}

	self.text = dayLabel.text;

	self.add(dayLabel);

	return self;
};

var dayOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

var monthName = ['January', 'February', 'March', 'April', 'May', 'June',
				 'July', 'August', 'September', 'October', 'November', 'December'];

exports = CalendarView;
<commit_msg>non current days in calendar display grayed out<commit_after>// CalendarView
// Author:  R. M. Salter
var db = require('lib/db');
var screenWidth = Ti.Platform.displayCaps.platformWidth;
var util = require('lib/Util');

// exported function CalendarView returns a new monthly view
// dis_date is the date whose year and month are to be displayed; sel_date is currently selected JS date
// _cb is a callback function that is invoked on the new selected JS date when one is selected

function CalendarView(dis_date, sel_date, _cb) {
	// break down display date -- only need month and year
	var dyr = dis_date.getFullYear(), dmo = dis_date.getMonth();
	// break down selected date
	var syr = sel_date.getFullYear(), smo = sel_date.getMonth(), sda = sel_date.getDate();
	// what's today's date?
	today = new Date();
	// break down today
	var tyr = today.getFullYear(), tmo = today.getMonth(), tda = today.getDate();
	var toolBar = makeToolBar(dyr, dmo);
	var cal = calendar(dyr, dmo, syr, smo, sda, tyr, tmo, tda, _cb);
	// Main View of the Month View.
	var self = Ti.UI.createView({layout: 'vertical'});
	self.add(toolBar);
	self.add(cal);

	// if 'up' increment month, 'down' decrement
	self.shiftMonth = function(direction) {
		if (direction == 'up') {
			if (dmo == 11) {
				dyr++;
				dmo = 0;
			} else {
				dmo++;
			}
		} else if (direction == 'down') {
			if (dmo == 0) {
				dyr--;
				dmo = 11;
			} else {
				dmo--;
			}
		}
		toolBar = makeToolBar(dyr, dmo);
		cal = calendar(dyr, dmo, syr, smo, sda, tyr, tmo, tda, _cb);
		self.removeAllChildren();
		self.add(toolBar);
		self.add(cal);
	};

	Ti.API.addEventListener('setCalDate', function(e) {
		if (sameDate(dis_date, e.date) && sameDate(sel_date, e.date)) return;
		sel_date = e.date;
		dis_date = e.date;
		// break down selected date
		var syr = sel_date.getFullYear(), smo = sel_date.getMonth(), sda = sel_date.getDate();
		toolBar = makeToolBar(syr, smo);
		cal = calendar(syr, smo, syr, smo, sda, tyr, tmo, tda, _cb);
		self.removeAllChildren();
		self.add(toolBar);
		self.add(cal);
	});
	return self;
}

// Help function to identify to JS dates that represent the same real date

function sameDate(d0, d1) {
	return d0.getFullYear() == d1.getFullYear()
		&& d0.getMonth() == d1.getMonth()
		&& d0.getDate() == d1.getDate();
}

// Builds the toolbar for a give year and month

function makeToolBar(yr, mo) {
	// Tool Bar
	var toolBar = Ti.UI.createView({
		width : screenWidth,
		height : 50,
		backgroundColor : util.CalendarWindowColor.BACKGROUND_COLOR,
		layout : 'vertical'
	});
	// Tool Bar Title
	var toolBarTitle = Ti.UI.createView({
		top : '3dp',
		width : '322dp',
		height : '24dp'
	});
	// Month Title - Tool Bar
	var monthTitle = Ti.UI.createLabel({
		width : 200,
		height : 24,
		text: monthName[mo]+' '+yr,
		textAlign : 'center',
		color : util.CalendarWindowColor.TEXT_COLOR,
		font : {
			fontSize : 20,
			fontWeight : 'bold'
		}
	});
	toolBarTitle.add(monthTitle);
	// Tool Bar Day
	var toolBarDays = Ti.UI.createView({
		top : 2,
		width : 322,
		height : 22,
		layout : 'horizontal',
		left : 0
	});
	var dayLabel = function(daytxt) {
		return Ti.UI.createLabel({
			left : '0dp',
			height : '20dp',
			text : daytxt,
			width : '46dp',
			textAlign : 'center',
			font : {
				fontSize : 12,
				fontWeight : 'bold'
			},
			color : util.CalendarWindowColor.TEXT_COLOR
		});
	};
	for (var i in dayOfWeek) toolBarDays.add(dayLabel(dayOfWeek[i]));
	// Adding Tool Bar Title View & Tool Bar Days View
	toolBar.add(toolBarTitle);
	toolBar.add(toolBarDays);
	return toolBar;
}

// Builds the calendar for a given year and month (yr and mo)
// syr, smo and sda are the selected year, month and day
// tyr, tmo and tda are today
// _cb is the callback applied to the new selected date when one is selected

var calendar = function(yr, mo, syr, smo, sda, tyr, tmo, tda, _cb) {
	// yr,mo,da are selected day; tyr,tmo,tda are today
	//create main calendar view
	var mainView = Ti.UI.createView({
		layout : 'horizontal',
		width : 322,
		height : 'auto',
		cb : _cb
	});

	// determine the cal data
	var isCurrentMonth = (yr == tyr && mo == tmo);
	var isSelectedMonth = (yr == syr && mo == smo);
	var daysInMonth = 32 - new Date(yr, mo, 32).getDate();
	var dayOfMonthToday = tda;
	var dayOfWeek = new Date(yr, mo, 1).getDay();
	var daysInLastMonth = 32 - new Date(yr, mo-1, 32).getDate();
	var daysInNextMonth = (new Date(yr, mo, daysInMonth).getDay()) - 6;
	//set initial day of week number
	var dayNumber = daysInLastMonth - dayOfWeek + 1;
	//get last month's days
	for ( i = 0; i < dayOfWeek; i++) {
		mainView.add(new dayView({
			day : dayNumber,
			taskcount : db.daycount(new Date(yr, mo, dayNumber)),
			color : '#8e959f',
			current : 'no',
		}));
		dayNumber++;
	};
	// reset day number for current month
	dayNumber = 1;
	//get this month's days
	var oldDay = {};
	for ( i = 0; i < daysInMonth; i++) {
		var newDay = new dayView({
			day : dayNumber,
			taskcount : db.daycount(new Date(yr, mo, dayNumber)),
			color : '#3a4756',
			current : 'yes',
		});
		mainView.add(newDay);
		// if this day is today, show it
		if (isCurrentMonth && tda == dayNumber) {
			newDay.color = 'white';
			newDay.backgroundColor = '#FFFFF000';
			oldDay = newDay;
		}
		// if this day is the chosen day, select it
		if (isSelectedMonth && dayNumber == sda) select(newDay);
	    dayNumber++;
	}
	// reset day number for next month
	dayNumber = 1;
	//get remaining month's days
	for ( i = 0; i > daysInNextMonth; i--) {
		  mainView.add(new dayView({
			 day : dayNumber,
			 taskcount : db.daycount(new Date(yr, mo, dayNumber)),
			 color : '#8e959f',
			 current : 'no',
		  }));
	     dayNumber++;
	 }
	// day selection event listener
	mainView.addEventListener('click', function(e) {
		if (e.source.current == 'yes') {
			select(e.source);
			if (mainView.cb != null) mainView.cb(new Date(yr, mo, e.source.text));
		}
	});
	return mainView;

	// function to highlight selected day
	function select(dayView) {
		if (isCurrentMonth && oldDay.text == dayOfMonthToday) {
			oldDay.color = 'white';
			oldDay.backgroundColor = '#FFFFF000';
		} else {
			oldDay.color = '#3a4756';
			oldDay.backgroundColor = '#FFDCDCDF';
		}
		oldDay.backgroundPaddingLeft = 0;
		oldDay.backgroundPaddingBottom = 0;
		if (isCurrentMonth && dayView.text == dayOfMonthToday) {
			dayView.backgroundColor = '#FFFF00FF';
		} else {
			dayView.backgroundColor = '#FFFF0000';
		}
		dayView.backgroundPaddingLeft = 1;
		dayView.backgroundPaddingBottom = 1;
		dayView.color = 'white';
		oldDay = dayView;
	};
};

// creates a label for a day given an object containing date
// of month and color

function dayView(e) {
	var self = Ti.UI.createView({
		width : '46dp',
		height : '44dp',
		current: e.current,
		color: e.color,
		backgroundColor : util.CalendarWindowColor.BACKGROUND_COLOR,
		borderColor: util.CalendarWindowColor.BORDER_COLOR,
		borderWidth: '1dp'
	});

	var dayLabel = Ti.UI.createLabel({
		text : e.day,
		textAlign : 'center',
		color: e.current == 'yes' ? 'black' : '#888888',
		current: e.current,
		font : {
			fontSize : 20,
			fontWeight : 'bold'
		}
	});

	if (e.taskcount) {
		var taskNotifier = Ti.UI.createLabel({
			text: e.taskcount,
			textAlign: 'center',
			right: '2dp',
			top: '2dp',
			backgroundColor: 'orange',
			color: 'black',
			font: {
				fontSize: 9,
				fontWeight: 'bold'
			}
		});
		self.add(taskNotifier);
	}

	self.text = dayLabel.text;

	self.add(dayLabel);

	return self;
};

var dayOfWeek = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

var monthName = ['January', 'February', 'March', 'April', 'May', 'June',
				 'July', 'August', 'September', 'October', 'November', 'December'];

exports = CalendarView;
<|endoftext|>


<commit_before>// TODO container and component in one. Split later.

import React from 'react'
import { connect } from 'react-redux'

import '../../css/CharacterGenerator.css'

import ActionBar from './ActionBar.js'
import Select from './Select.js'

const getStyles = (charData) => ({
  display: charData.mode !== 'edit' ? 'none' : ''
})

const AppComponent = ({
  appData, ancestryData, charData,
  changeAncestry, changeValue, setEditMode, setViewMode, createRandomCharacter
}) => (

    <ActionBar mode={charData.mode} onEdit={setEditMode} onView={setViewMode} onCreate={createRandomCharacter} />

Character Creation (Orc or Human)

        Ancestry
        <Select id='ancestry'
          options={appData.ancestries} value={charData.ancestry}
          onChange={(event) => changeAncestry(event.target.value)}
        />

        Name
        <Select id='name'
          options={ancestryData.commonNames} value={charData.name}
          onChange={(event) => changeValue('name', event.target.value)}
        />

        Background
        <Select id='background'
          options={ancestryData.background} value={charData.background}
          onChange={(event) => changeValue('background', event.target.value)}
        />

)

// Inbound data
const mapStateToProps = (state) => {
  return {
    appData: state.app,
    ancestryData: state.app[state.char.ancestry.toLowerCase()],
    charData: state.char
  }
}

const mapDispatchToProps = (dispatch) => ({
  changeAncestry: (value) => {
    dispatch({ type: 'CHANGE_ANCESTRY', value: value })
  },
  changeValue: (name, value) => {
    dispatch({ type: 'CHANGE_SIMPLE_VALUE', name: name, value: value })
  },
  setEditMode: () => {
    dispatch({ type: 'CHANGE_SIMPLE_VALUE', name: 'mode', value: 'edit' })
  },
  setViewMode: () => {
    dispatch({ type: 'CHANGE_SIMPLE_VALUE', name: 'mode', value: 'view' })
  },
  createRandomCharacter: () => {
    dispatch({ type: 'CREATE_RANDOM' })
  }
})

const App = connect(
  mapStateToProps,
  mapDispatchToProps
)(AppComponent)

export default App
<commit_msg>Fix caps issue for Travis.<commit_after>// TODO container and component in one. Split later.

import React from 'react'
import { connect } from 'react-redux'

import '../../css/characterGenerator.css'

import ActionBar from './ActionBar.js'
import Select from './Select.js'

const getStyles = (charData) => ({
  display: charData.mode !== 'edit' ? 'none' : ''
})

const AppComponent = ({
  appData, ancestryData, charData,
  changeAncestry, changeValue, setEditMode, setViewMode, createRandomCharacter
}) => (

    <ActionBar mode={charData.mode} onEdit={setEditMode} onView={setViewMode} onCreate={createRandomCharacter} />

Character Creation (Orc or Human)

        Ancestry
        <Select id='ancestry'
          options={appData.ancestries} value={charData.ancestry}
          onChange={(event) => changeAncestry(event.target.value)}
        />

        Name
        <Select id='name'
          options={ancestryData.commonNames} value={charData.name}
          onChange={(event) => changeValue('name', event.target.value)}
        />

        Background
        <Select id='background'
          options={ancestryData.background} value={charData.background}
          onChange={(event) => changeValue('background', event.target.value)}
        />

)

// Inbound data
const mapStateToProps = (state) => {
  return {
    appData: state.app,
    ancestryData: state.app[state.char.ancestry.toLowerCase()],
    charData: state.char
  }
}

const mapDispatchToProps = (dispatch) => ({
  changeAncestry: (value) => {
    dispatch({ type: 'CHANGE_ANCESTRY', value: value })
  },
  changeValue: (name, value) => {
    dispatch({ type: 'CHANGE_SIMPLE_VALUE', name: name, value: value })
  },
  setEditMode: () => {
    dispatch({ type: 'CHANGE_SIMPLE_VALUE', name: 'mode', value: 'edit' })
  },
  setViewMode: () => {
    dispatch({ type: 'CHANGE_SIMPLE_VALUE', name: 'mode', value: 'view' })
  },
  createRandomCharacter: () => {
    dispatch({ type: 'CREATE_RANDOM' })
  }
})

const App = connect(
  mapStateToProps,
  mapDispatchToProps
)(AppComponent)

export default App
<|endoftext|>


<commit_before>import React from "react";
import {compose, lifecycle} from "recompose";
import {getOr, isEmpty} from "lodash/fp";
import simple, {css} from "react-simple";
import {Link} from "react-router-dom";
import FaBeer from "react-icons/lib/fa/backward";

import {View} from "./core";
import {addWeatherData} from "./weather-data";
import WindChart from "./WindChart";
import LatestClouds from "./LatestClouds";
import {LatestGust, LatestWindAvg, addLatestGust} from "./LatestWindReadings";
import BrowserTitle from "./BrowserTitle";

const getPoints = getOr([], ["points"]);

const combineObsFore = (obs, avg) => getPoints(obs)
    .map(d => ({
        ...d,
        type: "observation",
    }))
    .concat(
        getPoints(avg).slice(0, 6).map(d => ({
            ...d,
            type: "forecast",
        }))
    );

const Row = simple(View, {
    marginTop: 10,
    flexDirection: "row",
    justifyContent: "center",
    flexWrap: "wrap",
});

const Title = simple(View, {
    fontSize: 45,
    fontWeight: "bold",
    color: "white",
});

const SubTitle = simple(View, {
    fontSize: 25,
});

const swing = css.keyframes({
    "0%": {transform: "rotate(60deg)"},
    "50%": {transform: "rotate(-60deg)"},
    "100%": {transform: "rotate(60deg)"},
});

const rotate = css.keyframes({
    "0%": {transform: "rotate(0deg)"},
    "100%": {transform: "rotate(360deg)"},
});

const Parachute = simple(
    View,
    {
        background: "url(/parachute.svg)",
        backgroundSize: "contain",
        width: 230,
        backgroundRepeat: "no-repeat !important",
        backgroundPosition: "center",
        height: 250,
        marginTop: 10,
        opacity: 0.08,
    },
    {
        swing: {
            animation: `${swing} 2s ease-in-out infinite`,
            transformOrigin: "50% 0%",
        },
        rotate: {
            animation: `${rotate} 0.8s linear infinite`,
            transformOrigin: "50% 15%",
        },
    }
);

var ConnectedParachute = ({value}) => {
    // value = 8;
    var gust = parseFloat(value, 10);
    if (gust >= 11) {
        return <Parachute rotate />;
    }

    if (gust >= 8) {
        return <Parachute swing />;
    }

    return <Parachute />;
};
ConnectedParachute = addLatestGust(ConnectedParachute);

const ParachuteContainer = simple(View, {
    position: "absolute",
    alignItems: "center",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
});

const TitleLink = simple(View.create(Link), {
    color: "white",
    flexDirection: "row",
    position: "absolute",
    left: 1,
    top: 1,
    fontSize: 20,
    textDecoration: "none",
    alignItems: "center",
});

const Sky = simple(View, {
    backgroundColor: "skyblue",
    paddingBottom: 50,
    overflow: "hidden",
    marginBottom: 25,
    minHeight: 300,
});

const CloudContainer = simple(Row, {
    marginTop: 35,
});

var Dz = ({dzProps, gusts, windAvg, gustForecasts, windAvgForecasts}) => {
    const dataMissing = [
        isEmpty(getPoints(gusts)),
        isEmpty(getPoints(windAvg)),
        isEmpty(getPoints(gustForecasts)),
        isEmpty(getPoints(windAvgForecasts)),
    ].some(Boolean);

    const combinedGusts = combineObsFore(gusts, gustForecasts);
    const combinedAvg = combineObsFore(windAvg, windAvgForecasts);

    return (
        <View>
            <BrowserTitle title={dzProps.icaocode} />
            <Sky>
                <ParachuteContainer>
                    <ConnectedParachute />
                </ParachuteContainer>

                <Row>
                    <Title>{dzProps.icaocode}</Title>
                </Row>

                <Row>
                    <LatestGust />
                    <LatestWindAvg />
                </Row>

                <CloudContainer>
                    <LatestClouds />
                </CloudContainer>

            </Sky>

            {!dataMissing &&
                <View>
                    <Row>
                        <SubTitle>Tuulihavainnot ja ennusteet</SubTitle>
                    </Row>
                    <WindChart gusts={combinedGusts} avg={combinedAvg} />
                </View>}

            <TitleLink to="/"><FaBeer />hyppykeli.fi</TitleLink>
        </View>
    );
};
Dz = compose(
    addWeatherData,
    lifecycle({
        componentDidMount() {
            this.props.fetchAll();
        },
    })
)(Dz);

export default Dz;
<commit_msg>Bigger back button<commit_after>import React from "react";
import {compose, lifecycle} from "recompose";
import {getOr, isEmpty} from "lodash/fp";
import simple, {css} from "react-simple";
import {Link} from "react-router-dom";
import BackArrow from "react-icons/lib/fa/backward";

import {View} from "./core";
import {addWeatherData} from "./weather-data";
import WindChart from "./WindChart";
import LatestClouds from "./LatestClouds";
import {LatestGust, LatestWindAvg, addLatestGust} from "./LatestWindReadings";
import BrowserTitle from "./BrowserTitle";

const getPoints = getOr([], ["points"]);

const combineObsFore = (obs, avg) => getPoints(obs)
    .map(d => ({
        ...d,
        type: "observation",
    }))
    .concat(
        getPoints(avg).slice(0, 6).map(d => ({
            ...d,
            type: "forecast",
        }))
    );

const Row = simple(View, {
    marginTop: 10,
    flexDirection: "row",
    justifyContent: "center",
    flexWrap: "wrap",
});

const Sep = simple(View, {
    width: 10,
    height: 10,
});

const Title = simple(View, {
    fontSize: 45,
    fontWeight: "bold",
    color: "white",
});

const SubTitle = simple(View, {
    fontSize: 25,
});

const swing = css.keyframes({
    "0%": {transform: "rotate(60deg)"},
    "50%": {transform: "rotate(-60deg)"},
    "100%": {transform: "rotate(60deg)"},
});

const rotate = css.keyframes({
    "0%": {transform: "rotate(0deg)"},
    "100%": {transform: "rotate(360deg)"},
});

const Parachute = simple(
    View,
    {
        background: "url(/parachute.svg)",
        backgroundSize: "contain",
        width: 230,
        backgroundRepeat: "no-repeat !important",
        backgroundPosition: "center",
        height: 250,
        marginTop: 10,
        opacity: 0.08,
    },
    {
        swing: {
            animation: `${swing} 2s ease-in-out infinite`,
            transformOrigin: "50% 0%",
        },
        rotate: {
            animation: `${rotate} 0.8s linear infinite`,
            transformOrigin: "50% 15%",
        },
    }
);

var ConnectedParachute = ({value}) => {
    // value = 8;
    var gust = parseFloat(value, 10);
    if (gust >= 11) {
        return <Parachute rotate />;
    }

    if (gust >= 8) {
        return <Parachute swing />;
    }

    return <Parachute />;
};
ConnectedParachute = addLatestGust(ConnectedParachute);

const ParachuteContainer = simple(View, {
    position: "absolute",
    alignItems: "center",
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
});

const TitleLink = simple(View.create(Link), {
    color: "white",
    flexDirection: "row",
    position: "absolute",
    left: 1,
    top: 1,
    fontSize: 25,
    textDecoration: "none",
    alignItems: "center",
});

const Sky = simple(View, {
    backgroundColor: "skyblue",
    paddingBottom: 50,
    paddingTop: 25,
    overflow: "hidden",
    marginBottom: 25,
    minHeight: 300,
});

const CloudContainer = simple(Row, {
    marginTop: 35,
});

var Dz = ({dzProps, gusts, windAvg, gustForecasts, windAvgForecasts}) => {
    const dataMissing = [
        isEmpty(getPoints(gusts)),
        isEmpty(getPoints(windAvg)),
        isEmpty(getPoints(gustForecasts)),
        isEmpty(getPoints(windAvgForecasts)),
    ].some(Boolean);

    const combinedGusts = combineObsFore(gusts, gustForecasts);
    const combinedAvg = combineObsFore(windAvg, windAvgForecasts);

    return (
        <View>
            <BrowserTitle title={dzProps.icaocode} />
            <Sky>
                <ParachuteContainer>
                    <ConnectedParachute />
                </ParachuteContainer>

                <Row>
                    <Title>{dzProps.icaocode}</Title>
                </Row>

                <Row>
                    <LatestGust />
                    <LatestWindAvg />
                </Row>

                <CloudContainer>
                    <LatestClouds />
                </CloudContainer>

            </Sky>

            {!dataMissing &&
                <View>
                    <Row>
                        <SubTitle>Tuulihavainnot ja ennusteet</SubTitle>
                    </Row>
                    <WindChart gusts={combinedGusts} avg={combinedAvg} />
                </View>}

            <TitleLink to="/"><BackArrow /><Sep />Hyppykeli.fi</TitleLink>
        </View>
    );
};
Dz = compose(
    addWeatherData,
    lifecycle({
        componentDidMount() {
            this.props.fetchAll();
        },
    })
)(Dz);

export default Dz;
<|endoftext|>


<commit_before>/*globals $,console,d3,cookieJar,formatDate,github,opr,InstallTrigger,Blob */
/*!
 * aggregitor.js
 *
 * Copyright 2016 Timothy Davenport; Licensed MIT
 */
var DAYS_IN_WEEK = 7,
    HOURS_IN_DAY = 24,
    WEEKS_IN_YEAR = 52,
    S_IN_M = 60,
    M_IN_H = 60,
    MS_IN_S = 1000,
    PC_COMMIT_INDEX = 2,
    MS_IN_DAY = HOURS_IN_DAY * M_IN_H * S_IN_M * MS_IN_S;

(function () {
    'use strict';
    window.aggregitor = {
        process_punch_cards : function (user) {
            /* Takes punch cards from repo/stats and puts them in packaged form of {repo0: punch_card0, repo1: punch_card1}.
            each punch card is an array of [d, h, c], where d = weekday, h = 24 hour, and c = number of commits. punch cards
            are pre filled with 0 so that empty or unavailable repos will be aggregated gracefully later.
             */
            var punch_cards = {}
                punch_card = [],
                h = 0,
                d = 0,
                i = 0,
                key = '',
                repo = {};

            // Aggregate punch card data
            console.log('Aggregating Punch Card:');
            // Loop thru repos
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];

                    // Fill empty punchcard for this repo
                    punch_card = [];
                    for (d = 0; d < DAYS_IN_WEEK; d += 1) {
                        for (h = 0; h < HOURS_IN_DAY; h += 1) {
                            punch_card.push([d, h, 0]);
                        }
                    }
                    // If there is a punch card for this repo, get it.
                    if (repo.hasOwnProperty('stats') &&
                        repo.stats.hasOwnProperty('punch_card') &&
                        !$.isEmptyObject(repo.stats.punch_card)) {
                        console.log('    ' + repo.name);
                        for (i = 0; i < repo.stats.punch_card.length; i += 1) {
                            punch_card[i][PC_COMMIT_INDEX] += repo.stats.punch_card[i][PC_COMMIT_INDEX];
                        }
                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate punch_card');
                    }
                    // add to punch_cards
                    punch_cards[key] = punch_card;
                }
            }
            return punch_cards;
        },
        process_code_frequency : function () {

        },
        process_commit_activity : function () {
            /* Takes commit activity from repo/stats and puts them in packaged form of
            {repo0: commit_activity0, repo1: commit_activity1}.
            each commit activity is an object with 'Y-m-d' keys and number of commit values.
             */
            var commit_activities = {},
                commit_activity = {},
                d = 0,
                w = 0,
                weekdate = null,
                date = null,
                date_str = '',
                key = '',
                repo = {};

            console.log('Aggregating Code Activity:');
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];

                    // If there is commit activity for this repo, get it.
                    if (repo.hasOwnProperty('stats') &&
                        repo.stats.hasOwnProperty('commit_activity') &&
                        !$.isEmptyObject(repo.stats.commit_activity)) {
                        console.log('    ' + repo.name);
                        // Loop thru 52 weeks
                        for (w = 0; w < WEEKS_IN_YEAR; w += 1) {
                            // Get date for this week
                            weekdate = new Date(repo.stats.commit_activity[w].week * MS);
                            // Loop thru days of each week
                            for (d = 0; d < DAYS_IN_WEEK; d += 1) {
                                // Get date of that day based on offset from week start date
                                date = new Date(weekdate.getTime() + d * MS_IN_DAY);
                                // Convert date into YYYY-MM-DD string
                                date_str = '{0}-{1}-{2}'.format(
                                    date.getFullYear(),
                                    ('0' + (date.getMonth() + 1)).slice(-2),
                                    ('0' + date.getDate()).slice(-2)
                                );
                                // Add that day's commits
                                commit_activity[date_str] += repo.stats.commit_activity[w].days[d];
                            }
                        }
                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate commit_activity');
                    }
                }
                commit_activities[key] = commit_activity;
            }

            // Once all commit_activities are converted to date list, ensure all dates exist for each repo
            // TBD

            return commit_activities;
        },
        process_contributors : function () {

        },
        process_participation : function () {
            /* Takes participation from repo/stats and puts them in packaged form of
            {repo0: participation0, repo1: participation1}.
            each participation is an object with 'owner' and 'all' arrays of weekly partication commit numbers. participation
            arrays are pre filled with 0 so that empty or unavailable repos will be aggregated gracefully later.
             */
            var participations = {},
                participation = {},
                w = 0,
                z = 0,
                key = '',
                repo = {};

            // Aggregate participation data
            console.log('Aggregating Participation:');
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];participation

                    // Fill empty participation
                    participation = {owner: [], all: []};
                    for (w = 0; w < WEEKS_IN_YEAR; w += 1) {
                        participation.owner.push(0);
                        participation.all.push(0);
                    }

                    // If there is commit activity for this repo, get it.
                    if (repo.hasOwnProperty('stats') &&
                        repo.stats.hasOwnProperty('participation') &&
                        !$.isEmptyObject(repo.stats.participation)) {
                        console.log('    ' + repo.name);
                        // Loop thru each week
                        for (w = 0; w < WEEKS_IN_YEAR; w += 1) {
                            // Add owner and all particiation for the week
                            participation.owner[w] += repo.stats.participation.owner[w];
                            participation.all[w] += repo.stats.participation.all[w];
                        }
                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate participation');
                    }
                }
                participations[key] = particiation;
            }
            return participations;
        }
    };
}());
<commit_msg>create code_frequency pre processor and lint<commit_after>/*globals $,console,d3,cookieJar,formatDate,github,opr,InstallTrigger,Blob */
/*!
 * aggregitor.js
 *
 * Copyright 2016 Timothy Davenport; Licensed MIT
 */
var DAYS_IN_WEEK = 7,
    HOURS_IN_DAY = 24,
    WEEKS_IN_YEAR = 52,
    S_IN_M = 60,
    M_IN_H = 60,
    MS_IN_S = 1000,
    PC_COMMIT_INDEX = 2,
    CF_WEEK_INDEX = 0,
    CF_A_INDEX = 1,
    CF_D_INDEX = 2,
    MS_IN_DAY = HOURS_IN_DAY * M_IN_H * S_IN_M * MS_IN_S;

(function () {
    'use strict';
    window.aggregitor = {
        process_punch_cards : function (user) {
            /* Takes punch cards from repo/stats and puts them in packaged form of {repo0: punch_card0, repo1: punch_card1}.
            each punch card is an array of [d, h, c], where d = weekday, h = 24 hour, and c = number of commits. punch cards
            are pre filled with 0 so that empty or unavailable repos will be aggregated gracefully later.
             */
            var punch_cards = {},
                punch_card = [],
                h = 0,
                d = 0,
                i = 0,
                key = '',
                repo = {};

            // Aggregate punch card data
            console.log('Aggregating Punch Card:');
            // Loop thru repos
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];

                    // Fill empty punchcard for this repo
                    punch_card = [];
                    for (d = 0; d < DAYS_IN_WEEK; d += 1) {
                        for (h = 0; h < HOURS_IN_DAY; h += 1) {
                            punch_card.push([d, h, 0]);
                        }
                    }
                    // If there is a punch card for this repo, get it.
                    if (repo.hasOwnProperty('stats') && repo.stats.hasOwnProperty('punch_card') && !$.isEmptyObject(repo.stats.punch_card)) {
                        console.log('    ' + repo.name);
                        for (i = 0; i < repo.stats.punch_card.length; i += 1) {
                            punch_card[i][PC_COMMIT_INDEX] += repo.stats.punch_card[i][PC_COMMIT_INDEX];
                        }
                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate punch_card');
                    }
                    // add to punch_cards
                    punch_cards[key] = punch_card;
                }
            }
            return punch_cards;
        },
        process_code_frequency : function (user) {
            /* Takes code frequency from repo/stats and puts them in packaged form of
            {repo0: code_frequency0, repo1: code_frequency1}.
            each code frequency is an array of [w, a, d], where w = week, a = number of additions, and d = number of
            deletions. ode frequencies are pre filled with 0 so that empty or unavailable repos will be aggregated gracefully
            later.
            */
            var code_frequencies = {},
                code_frequency = {},
                w = 0,
                weekdate = null,
                date_str = '',
                key = '',
                repo = {};

            console.log('Aggregating Code Frequency:');
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];

                    // Fill empty code_frequency for this repo
                    code_frequency = {};

                    // If there is code frequency for this repo, get it.
                    if (repo.hasOwnProperty('stats') && repo.stats.hasOwnProperty('code_frequency') && !$.isEmptyObject(repo.stats.code_frequency)) {
                        console.log('    ' + repo.name);

                        // Loop thru ? weeks
                        for (w = 0; w < repo.stats.code_frequency.length; w += 1) {
                            // Get date for this week
                            weekdate = new Date(repo.stats.code_frequency[w][CF_WEEK_INDEX] * MS_IN_S);
                            // Convert date into YYYY-MM-DD string
                            date_str = '{0}-{1}-{2}'.format(
                                weekdate.getFullYear(),
                                ('0' + (weekdate.getMonth() + 1)).slice(-2),
                                ('0' + weekdate.getDate()).slice(-2)
                            );
                            // Add that week's additions and deletions
                            code_frequency[date_str] = {
                                'a' : repo.stats.code_frequency[w][CF_A_INDEX],
                                'd' : repo.stats.code_frequency[w][CF_D_INDEX]
                            };
                        }

                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate code_frequency');
                    }
                    // add to code_frequencies
                    code_frequencies[key] = code_frequency;
                }
            }

            // Once all commit_activities are converted to date list, ensure all dates exist for each repo
            // TBD

            return code_frequencies;
        },
        process_commit_activity : function (user) {
            /* Takes commit activity from repo/stats and puts them in packaged form of
            {repo0: commit_activity0, repo1: commit_activity1}.
            each commit activity is an object with 'Y-m-d' keys and number of commit values.
             */
            var commit_activities = {},
                commit_activity = {},
                d = 0,
                w = 0,
                weekdate = null,
                date = null,
                date_str = '',
                key = '',
                repo = {};

            console.log('Aggregating Commit Activity:');
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];

                    // Fill empty commit_activity for this repo
                    commit_activity = {};

                    // If there is commit activity for this repo, get it.
                    if (repo.hasOwnProperty('stats') && repo.stats.hasOwnProperty('commit_activity') && !$.isEmptyObject(repo.stats.commit_activity)) {
                        console.log('    ' + repo.name);
                        // Loop thru 52 weeks
                        for (w = 0; w < WEEKS_IN_YEAR; w += 1) {
                            // Get date for this week
                            weekdate = new Date(repo.stats.commit_activity[w].week * MS_IN_S);
                            // Loop thru days of each week
                            for (d = 0; d < DAYS_IN_WEEK; d += 1) {
                                // Get date of that day based on offset from week start date
                                date = new Date(weekdate.getTime() + d * MS_IN_DAY);
                                // Convert date into YYYY-MM-DD string
                                date_str = '{0}-{1}-{2}'.format(
                                    date.getFullYear(),
                                    ('0' + (date.getMonth() + 1)).slice(-2),
                                    ('0' + date.getDate()).slice(-2)
                                );
                                // Add that day's commits
                                commit_activity[date_str] += repo.stats.commit_activity[w].days[d];
                            }
                        }
                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate commit_activity');
                    }
                    commit_activities[key] = commit_activity;
                }
            }

            // Once all commit_activities are converted to date list, ensure all dates exist for each repo
            // TBD

            return commit_activities;
        },
        process_contributors : function (user) {
            /*  */
            var contributors = {},
                contributor = {},
                w = 0,
                key = '',
                repo = {};

            return contributors;
        },
        process_participation : function (user) {
            /* Takes participation from repo/stats and puts them in packaged form of
            {repo0: participation0, repo1: participation1}.
            each participation is an object with 'owner' and 'all' arrays of weekly partication commit numbers. participation
            arrays are pre filled with 0 so that empty or unavailable repos will be aggregated gracefully later.
             */
            var participations = {},
                participation = {},
                w = 0,
                key = '',
                repo = {};

            // Aggregate participation data
            console.log('Aggregating Participation:');
            for (key in user.repos) {
                if (user.repos.hasOwnProperty(key)) {
                    repo = user.repos[key];

                    // Fill empty participation
                    participation = {owner: [], all: []};
                    for (w = 0; w < WEEKS_IN_YEAR; w += 1) {
                        participation.owner.push(0);
                        participation.all.push(0);
                    }

                    // If there is commit activity for this repo, get it.
                    if (repo.hasOwnProperty('stats') && repo.stats.hasOwnProperty('participation') && !$.isEmptyObject(repo.stats.participation)) {
                        console.log('    ' + repo.name);
                        // Loop thru each week
                        for (w = 0; w < WEEKS_IN_YEAR; w += 1) {
                            // Add owner and all particiation for the week
                            participation.owner[w] += repo.stats.participation.owner[w];
                            participation.all[w] += repo.stats.participation.all[w];
                        }
                    } else {
                        console.log('    ' + repo.name + ' ! could not aggregate participation');
                    }
                    participations[key] = participation;
                }
            }
            return participations;
        }
    };
}());
<|endoftext|>


<commit_before>(function () {
    var _ = require('lodash');
    var h = require('virtual-dom/h');
    var createElement = require('virtual-dom/create-element');
    var hot;
    function constructor(services) {
        var that = {};
        var element;
        var readOnly;
        that.load = function (_element_) {
            element = _element_;
            var wrapper = createElement(h('div'));
            element.appendChild(wrapper);
            readOnly = services.data.getUrl() ? true : false;
            var data = services.data.get();
            hot = new Handsontable(wrapper, {
                startRows: 8,
                startCols: 5,
                height: 500,
                stretchH: 'all',
                rowHeaders: true,
                colHeaders: true,
                contextMenu: true,
                data: data,
                afterChange: function () {
                    services.data.set(removeEmptyRows(this));
                },
                afterRemoveRow:function () {
                    services.data.set(removeEmptyRows(this));
                },
                afterRemoveCol:function (test) {
                    services.data.set(removeEmptyRows(this));
                }
            });
            hot.updateSettings({
                cells: function (row, col, prop) {
                    var cellProperties = {};
                    cellProperties.readOnly = readOnly;
                    return cellProperties;
                }
            });

            services.mediator.on('dataUpdate', function (_data_) {
                readOnly = services.data.getUrl() ? true : false;
                if(_data_.length > 0){
                    hot.updateSettings({
                        data: _data_,
                        cells: function (row, col, prop) {
                            var cellProperties = {};
                            cellProperties.readOnly = readOnly;
                            return cellProperties;
                        }
                    });
                } else {
                    hot.clear();
                }

            }, 'hot');
        };

        var Hook = function () {};
        Hook.prototype.hook = function (node) {
            setTimeout(function () {
                that.load(node);
            });
        };

        that.template = function () {
            return h('div', {
                'afterRender': new Hook()
            });
        };

        that.destroy = function () {
            services.mediator.off(null, null, 'hot');
            var data = removeEmptyRows(hot);
            if (!_.isEmpty(data)) {
                services.data.set(removeEmptyRows(hot));
            }
            hot.destroy();
            element.innerHTML = '';
        };

        function removeEmptyRows(hot) {
            var gridData = hot.getData();
            var cleanedGridData = [];
            _.forEach(gridData, function (object, rowKey) {
                if (!hot.isEmptyRow(rowKey)) cleanedGridData[rowKey] = object;
            });
            return cleanedGridData;
        }

        return that;
    }

    module.exports = constructor;
})();
<commit_msg>spareRow added to HOT<commit_after>(function () {
    //var _ = require('lodash');

    var _ = {
        forEach: require('lodash.foreach'),
        isEmpty: require('lodash.isempty'),
        isUndefined: require('lodash.isundefined')
    };

    var h = require('virtual-dom/h');
    var createElement = require('virtual-dom/create-element');
    var hot;
    function constructor(services) {
        var that = {};
        var element;
        var readOnly;
        that.load = function (_element_) {
            element = _element_;
            var wrapper = createElement(h('div'));
            element.appendChild(wrapper);
            readOnly = services.data.getUrl() ? true : false;

            var data = services.data.get();
            data = _.isUndefined(data[0]) ? [[]] : data;

            hot = new Handsontable(wrapper, {
                minRows: 1,
                minCols: 2,
                minSpareRows: 1,
                //minSpareCols: 1,
                height: 500,
                stretchH: 'all',
                rowHeaders: true,
                colHeaders: true,
                contextMenu: true,
                data: data,
                afterChange: function () {
                    services.data.set(removeEmptyRows(this));
                },
                afterRemoveRow:function () {
                    services.data.set(removeEmptyRows(this));
                },
                afterRemoveCol:function (test) {
                    services.data.set(removeEmptyRows(this));
                }
            });
            hot.updateSettings({
                cells: function (row, col, prop) {
                    var cellProperties = {};
                    cellProperties.readOnly = readOnly;
                    return cellProperties;
                }
            });

            services.mediator.on('dataUpdate', function (_data_) {
                readOnly = services.data.getUrl() ? true : false;
                if(_data_.length > 0){
                    hot.updateSettings({
                        data: _data_,
                        cells: function (row, col, prop) {
                            var cellProperties = {};
                            cellProperties.readOnly = readOnly;
                            return cellProperties;
                        }
                    });
                } else {
                    hot.clear();
                }

            }, 'hot');
        };

        var Hook = function () {};
        Hook.prototype.hook = function (node) {
            setTimeout(function () {
                that.load(node);
            });
        };

        that.template = function () {
            return h('div', {
                'afterRender': new Hook()
            });
        };

        that.destroy = function () {
            services.mediator.off(null, null, 'hot');
            var data = removeEmptyRows(hot);
            if (!_.isEmpty(data)) {
                services.data.set(removeEmptyRows(hot));
            }
            hot.destroy();
            element.innerHTML = '';
        };

        function removeEmptyRows(hot) {
            var gridData = hot.getData();
            var cleanedGridData = [];
            _.forEach(gridData, function (object, rowKey) {
                if (!hot.isEmptyRow(rowKey)) cleanedGridData[rowKey] = object;
            });
            return cleanedGridData;
        }

        return that;
    }

    module.exports = constructor;
})();
<|endoftext|>


<commit_before>import React, { Fragment, PureComponent } from 'react';
import { gql } from 'apollo-boost';
import { Query } from 'react-apollo';
import InfiniteScroll from 'react-infinite-scroller';
import Raven from 'raven';
import Meta from '../components/Meta';
import Header from '../components/Header';
import Release from '../components/Release';

const allReleasesQuery = gql`
  query allReleases($after: String) {
    repository(owner: "mcansh", name: "blog") {
      name
      releases(
        first: 10
        after: $after
        orderBy: { field: CREATED_AT, direction: DESC }
      ) {
        edges {
          cursor
          node {
            tag {
              name
            }
            description
            publishedAt
          }
        }
      }
    }
  }
`;

class Changelog extends PureComponent {
  state = {
    hasMore: true,
  };

  hasNoMore = () => this.setState({ hasMore: false });

  render() {
    const { hasMore } = this.state;
    return (
      <Fragment>
        <Meta />

        <Query query={allReleasesQuery}>
          {({ loading, error, fetchMore, data }) => {
            if (loading) return
Loading...
;

            if (error) {
              Raven.captureException(error);
              return
Error :(
;
            }

            const {
              repository: {
                releases: { edges: releases },
              },
            } = data;

            const loadMoreReleases = () => {
              const lastRelease = releases[releases.length - 1];

              fetchMore({
                variables: {
                  after: lastRelease.cursor,
                },
                updateQuery: (prev, { fetchMoreResult }) => {
                  if (fetchMoreResult.repository.releases.edges.length < 10) {
                    this.hasNoMore();
                  }

                  if (!fetchMoreResult.repository.releases.edges.length) {
                    return prev;
                  }

                  return {
                    repository: {
                      ...prev.repository,
                      releases: {
                        ...prev.repository.releases,
                        edges: [
                          ...prev.repository.releases.edges,
                          ...fetchMoreResult.repository.releases.edges,
                        ],
                      },
                    },
                  };
                },
              });
            };

            return (
              <InfiniteScroll loadMore={loadMoreReleases} hasMore={hasMore}>
                <Fragment>
                  {releases.map(({ node: release }) => (
                    <Release
                      key={release.tag.name}
                      version={release.tag.name}
                      notes={release.description}
                      date={release.publishedAt}
                    />
                  ))}
                </Fragment>
              </InfiniteScroll>
            );
          }}
        </Query>
      </Fragment>
    );
  }
}

export default Changelog;
<commit_msg>update infinite scroll threshold<commit_after>import React, { Fragment, PureComponent } from 'react';
import { gql } from 'apollo-boost';
import { Query } from 'react-apollo';
import InfiniteScroll from 'react-infinite-scroller';
import Raven from 'raven';
import Meta from '../components/Meta';
import Header from '../components/Header';
import Release from '../components/Release';

const allReleasesQuery = gql`
  query allReleases($after: String) {
    repository(owner: "mcansh", name: "blog") {
      name
      releases(
        first: 10
        after: $after
        orderBy: { field: CREATED_AT, direction: DESC }
      ) {
        edges {
          cursor
          node {
            tag {
              name
            }
            description
            publishedAt
          }
        }
      }
    }
  }
`;

class Changelog extends PureComponent {
  state = {
    hasMore: true,
  };

  hasNoMore = () => this.setState({ hasMore: false });

  render() {
    const { hasMore } = this.state;
    return (
      <Fragment>
        <Meta />

        <Query query={allReleasesQuery}>
          {({ loading, error, fetchMore, data }) => {
            if (loading) return
Loading...
;

            if (error) {
              Raven.captureException(error);
              return
Error :(
;
            }

            const {
              repository: {
                releases: { edges: releases },
              },
            } = data;

            const loadMoreReleases = () => {
              const lastRelease = releases[releases.length - 1];

              fetchMore({
                variables: {
                  after: lastRelease.cursor,
                },
                updateQuery: (prev, { fetchMoreResult }) => {
                  if (fetchMoreResult.repository.releases.edges.length < 10) {
                    this.hasNoMore();
                  }

                  if (!fetchMoreResult.repository.releases.edges.length) {
                    return prev;
                  }

                  return {
                    repository: {
                      ...prev.repository,
                      releases: {
                        ...prev.repository.releases,
                        edges: [
                          ...prev.repository.releases.edges,
                          ...fetchMoreResult.repository.releases.edges,
                        ],
                      },
                    },
                  };
                },
              });
            };

            return (
              <InfiniteScroll
                loadMore={loadMoreReleases}
                hasMore={hasMore}
                threshold={500}
              >
                <Fragment>
                  {releases.map(({ node: release }) => (
                    <Release
                      key={release.tag.name}
                      version={release.tag.name}
                      notes={release.description}
                      date={release.publishedAt}
                    />
                  ))}
                </Fragment>
              </InfiniteScroll>
            );
          }}
        </Query>
      </Fragment>
    );
  }
}

export default Changelog;
<|endoftext|>


<commit_before>define(['lodash', 'cryptojs', 'Utils'], function(_, CryptoJS, Utils) {
  var ID = function(bytes) {
    _.each(bytes, function(b) {
      if (_.isNaN(b) || !_.isNumber(b) || b < 0x00 || 0xff < b) {
        throw new Error("Invalid argument.");
      }
    });
    if (bytes.length !== ID._BYTE_SIZE) {
      throw new Error("Invalid argument.");
    }

    this._bytes = _.last(bytes, ID._BYTE_SIZE);
    this._hexString = _.map(this._bytes, function(b) {
      var str = b.toString(16);
      return b < 0x10 ? "0" + str : str;
    }).join("");
    this._bitLength = this._bytes.length * 8;
  };

  ID._BYTE_SIZE = 32;

  ID.create = function(str) {
    if (!Utils.isNonemptyString(str)) {
      throw new Error("Invalid argument.");
    }

    return new ID(ID._createBytes(str));
  };

  ID._createBytes = function(str) {
    var hash = CryptoJS.SHA256(str).toString(CryptoJS.enc.Hex);
    return ID._createBytesFromHexString(hash);
  };

  ID._createBytesFromHexString = function(str) {
    if (!Utils.isNonemptyString(str)) {
      throw new Error("Invalid argument.");
    }

    return _(Math.floor(str.length / 2)).times(function(i) {
      return parseInt(str.substr(i * 2, 2), 16);
    }).value();
  };

  ID.fromHexString = function(str) {
    return new ID(ID._createBytesFromHexString(str));
  };

  ID._addInBytes = function(bytes1, bytes2) {
    var copy = _.clone(bytes1);
    var carry = 0;
    for (var i = bytes1.length - 1; i >= 0; i--) {
      copy[i] += (bytes2[i] + carry);
      if (copy[i] < 0) {
        carry = -1;
        copy[i] += 0x100;
      } else {
        carry = copy[i] >> 8;
      }
      copy[i] &= 0xff;
    }
    return copy;
  };

  ID.prototype = {
    isInInterval: function(fromId, toId) {
      if (!fromId || !toId) {
        throw new Error("Invalid arguments.");
      }

      if (fromId.equals(toId)) {
        return !this.equals(fromId);
      }

      if (fromId.compareTo(toId) < 0) {
        return (this.compareTo(fromId) > 0 && this.compareTo(toId) < 0);
      }

      return ((this.compareTo(fromId) > 0 && this.compareTo(ID.maxId) <= 0 && !fromId.equals(ID.maxId)) ||
              (this.compareTo(ID.minId) >= 0 && this.compareTo(toId) < 0 && !ID.minId.equals(toId)));
    },

    addPowerOfTwo: function(powerOfTwo) {
      if (powerOfTwo < 0 || powerOfTwo >= this._bitLength) {
        throw new Error("Power of two out of index.");
      }

      var copy = _.clone(this._bytes);
      var indexOfBytes = this._bytes.length - 1 - Math.floor(powerOfTwo / 8);
      var valueToAdd = [1, 2, 4, 8, 16, 32, 64, 128][powerOfTwo % 8];
      for (var i = indexOfBytes; i >= 0; i--) {
        copy[i] += valueToAdd;
        valueToAdd = copy[i] >> 8;
        copy[i] &= 0xff;
        if (valueToAdd === 0) {
          break;
        }
      }

      return new ID(copy);
    },

    add: function(id) {
      return new ID(ID._addInBytes(this._bytes, id._bytes));
    },

    sub: function(id) {
      return new ID(ID._addInBytes(this._bytes, _.map(id._bytes, function(b) { return -b; })));
    },

    getIntervalInPowerOfTwoFrom: function(id) {
      if (this.equals(id)) {
        return -Infinity;
      }

      var diff = this.sub(id);
      for (var i = 0; i < this._bitLength; i++) {
        if (ID.minId.addPowerOfTwo(i).compareTo(diff) > 0) {
          if (i === 0) {
            return -Infinity;
          }
          break;
        }
      }
      return i - 1;
    },

    compareTo: function(id) {
      for (var i = 0; i < ID._BYTE_SIZE; i++) {
        if (this._bytes[i] < id._bytes[i]) {
          return -1;
        } else if (this._bytes[i] > id._bytes[i]) {
          return 1;
        }
      }
      return 0;
    },

    equals: function(id) {
      return this.compareTo(id) === 0;
    },

    getLength: function() {
      return this._bitLength;
    },

    toHexString: function() {
      return this._hexString;
    }
  };

  ID.minId = new ID(_(ID._BYTE_SIZE).times(function() {
    return 0x00;
  }).value());

  ID.maxId = new ID(_(ID._BYTE_SIZE).times(function() {
    return 0xff;
  }).value());

  return ID;
});
<commit_msg>Optimize ID.js<commit_after>define(['lodash', 'cryptojs', 'Utils'], function(_, CryptoJS, Utils) {
  var ID = function(bytes) {
    _.each(bytes, function(b) {
      if (_.isNaN(b) || !_.isNumber(b) || b < 0x00 || 0xff < b) {
        throw new Error("Invalid argument.");
      }
    });
    if (bytes.length !== ID._BYTE_SIZE) {
      throw new Error("Invalid argument.");
    }

    this._bytes = _.last(bytes, ID._BYTE_SIZE);
    this._hexString = _.map(this._bytes, function(b) {
      var str = b.toString(16);
      return b < 0x10 ? "0" + str : str;
    }).join("");
  };

  ID._BYTE_SIZE = 32;
  ID._BIT_LENGTH = ID._BYTE_SIZE * 8;

  ID.create = function(str) {
    if (!Utils.isNonemptyString(str)) {
      throw new Error("Invalid argument.");
    }

    return new ID(ID._createBytes(str));
  };

  ID._createBytes = function(str) {
    var hash = CryptoJS.SHA256(str).toString(CryptoJS.enc.Hex);
    return ID._createBytesFromHexString(hash);
  };

  ID._createBytesFromHexString = function(str) {
    if (!Utils.isNonemptyString(str)) {
      throw new Error("Invalid argument.");
    }

    return _(Math.floor(str.length / 2)).times(function(i) {
      return parseInt(str.substr(i * 2, 2), 16);
    }).value();
  };

  ID.fromHexString = function(str) {
    return new ID(ID._createBytesFromHexString(str));
  };

  ID._addInBytes = function(bytes1, bytes2) {
    var copy = _.clone(bytes1);
    var carry = 0;
    for (var i = bytes1.length - 1; i >= 0; i--) {
      copy[i] += (bytes2[i] + carry);
      if (copy[i] < 0) {
        carry = -1;
        copy[i] += 0x100;
      } else {
        carry = copy[i] >> 8;
      }
      copy[i] &= 0xff;
    }
    return copy;
  };

  ID.prototype = {
    isInInterval: function(fromId, toId) {
      if (!fromId || !toId) {
        throw new Error("Invalid arguments.");
      }

      if (fromId.equals(toId)) {
        return !this.equals(fromId);
      }

      if (fromId.compareTo(toId) < 0) {
        return (this.compareTo(fromId) > 0 && this.compareTo(toId) < 0);
      } else {
        return (this.compareTo(fromId) > 0 || this.compareTo(toId) < 0);
      }
    },

    addPowerOfTwo: function(powerOfTwo) {
      if (powerOfTwo < 0 || powerOfTwo >= ID._BIT_LENGTH) {
        throw new Error("Power of two out of index.");
      }

      var copy = _.clone(this._bytes);
      var indexOfBytes = this._bytes.length - 1 - Math.floor(powerOfTwo / 8);
      var valueToAdd = [1, 2, 4, 8, 16, 32, 64, 128][powerOfTwo % 8];
      for (var i = indexOfBytes; i >= 0; i--) {
        copy[i] += valueToAdd;
        valueToAdd = copy[i] >> 8;
        copy[i] &= 0xff;
        if (valueToAdd === 0) {
          break;
        }
      }

      return new ID(copy);
    },

    add: function(id) {
      return new ID(ID._addInBytes(this._bytes, id._bytes));
    },

    sub: function(id) {
      return new ID(ID._addInBytes(this._bytes, _.map(id._bytes, function(b) { return -b; })));
    },

    getIntervalInPowerOfTwoFrom: function(id) {
      if (this.equals(id)) {
        return -Infinity;
      }

      var diff = this.sub(id);
      for (var i = 0; i < ID._BIT_LENGTH; i++) {
        if (ID._powerOfTwos[i].compareTo(diff) > 0) {
          if (i === 0) {
            return -Infinity;
          }
          break;
        }
      }
      return i - 1;
    },

    compareTo: function(id) {
      for (var i = 0; i < ID._BYTE_SIZE; i++) {
        if (this._bytes[i] < id._bytes[i]) {
          return -1;
        } else if (this._bytes[i] > id._bytes[i]) {
          return 1;
        }
      }
      return 0;
    },

    equals: function(id) {
      return this.compareTo(id) === 0;
    },

    getLength: function() {
      return ID._BIT_LENGTH;
    },

    toHexString: function() {
      return this._hexString;
    }
  };

  ID.minId = new ID(_(ID._BYTE_SIZE).times(function() {
    return 0x00;
  }).value());

  ID.maxId = new ID(_(ID._BYTE_SIZE).times(function() {
    return 0xff;
  }).value());

  ID._powerOfTwos = _(ID.minId.getLength()).times(function(i) {
    return ID.minId.addPowerOfTwo(i);
  }).value();

  return ID;
});
<|endoftext|>