<commit_before>import {all_messages_data} from "./all_messages_data";
import * as message_lists from "./message_lists";
import * as message_scroll from "./message_scroll";
import * as message_util from "./message_util";
import * as message_viewport from "./message_viewport";
import * as navigate from "./navigate";
import * as overlays from "./overlays";
import * as settings_notifications from "./settings_notifications";
import * as stream_edit from "./stream_edit";
import * as stream_list from "./stream_list";

export function update_is_muted(sub, value) {
    sub.is_muted = value;

    setTimeout(() => {
        let msg_offset;
        let saved_ypos;
        // Save our current scroll position
        if (overlays.is_active() || overlays.is_modal_open()) {
            saved_ypos = message_viewport.scrollTop();
        } else if (
            message_lists.home === message_lists.current &&
            message_lists.current.selected_row().offset() !== null
        ) {
            msg_offset = message_lists.current.selected_row().offset().top;
        }

        message_lists.home.clear({clear_selected_id: false});

        // Recreate the message_lists.home with the newly filtered all_messages_data
        message_util.add_old_messages(all_messages_data.all_messages(), message_lists.home);

        // Ensure we're still at the same scroll position
        if (overlays.is_overlay_or_modal_open()) {
            message_viewport.scrollTop(saved_ypos);
        } else if (message_lists.home === message_lists.current) {
            // We pass use_closest to handle the case where the
            // currently selected message is being hidden from the
            // home view
            message_lists.home.select_id(message_lists.home.selected_id(), {
                use_closest: true,
                empty_ok: true,
            });
            if (message_lists.current.selected_id() !== -1) {
                message_lists.current.view.set_message_offset(msg_offset);
            }
        }

        // In case we added messages to what's visible in the home
        // view, we need to re-scroll to make sure the pointer is
        // still visible. We don't want the auto-scroll handler to
        // move our pointer to the old scroll location before we have
        // a chance to update it.
        navigate.plan_scroll_to_selected();
        message_scroll.suppress_selection_update_on_next_scroll();

        if (!message_lists.home.empty()) {
            message_util.do_unread_count_updates(message_lists.home.all_messages());
        }
    }, 0);

    settings_notifications.update_muted_stream_state(sub);
    stream_edit.update_muting_rendering(sub);
    stream_list.set_in_home_view(sub.stream_id, !sub.is_muted);
}
<commit_msg>stream_muting: Call the update_unread_counts directly.<commit_after>import {all_messages_data} from "./all_messages_data";
import * as message_lists from "./message_lists";
import * as message_scroll from "./message_scroll";
import * as message_util from "./message_util";
import * as message_viewport from "./message_viewport";
import * as navigate from "./navigate";
import * as overlays from "./overlays";
import * as settings_notifications from "./settings_notifications";
import * as stream_edit from "./stream_edit";
import * as stream_list from "./stream_list";
import * as unread_ui from "./unread_ui";

export function update_is_muted(sub, value) {
    sub.is_muted = value;

    setTimeout(() => {
        let msg_offset;
        let saved_ypos;
        // Save our current scroll position
        if (overlays.is_active() || overlays.is_modal_open()) {
            saved_ypos = message_viewport.scrollTop();
        } else if (
            message_lists.home === message_lists.current &&
            message_lists.current.selected_row().offset() !== null
        ) {
            msg_offset = message_lists.current.selected_row().offset().top;
        }

        message_lists.home.clear({clear_selected_id: false});

        // Recreate the message_lists.home with the newly filtered all_messages_data
        message_util.add_old_messages(all_messages_data.all_messages(), message_lists.home);

        // Ensure we're still at the same scroll position
        if (overlays.is_overlay_or_modal_open()) {
            message_viewport.scrollTop(saved_ypos);
        } else if (message_lists.home === message_lists.current) {
            // We pass use_closest to handle the case where the
            // currently selected message is being hidden from the
            // home view
            message_lists.home.select_id(message_lists.home.selected_id(), {
                use_closest: true,
                empty_ok: true,
            });
            if (message_lists.current.selected_id() !== -1) {
                message_lists.current.view.set_message_offset(msg_offset);
            }
        }

        // In case we added messages to what's visible in the home
        // view, we need to re-scroll to make sure the pointer is
        // still visible. We don't want the auto-scroll handler to
        // move our pointer to the old scroll location before we have
        // a chance to update it.
        navigate.plan_scroll_to_selected();
        message_scroll.suppress_selection_update_on_next_scroll();

        // Since muted streams aren't counted in visible unread
        // counts, we need to update the rendering of them.
        unread_ui.update_unread_counts();
    }, 0);

    settings_notifications.update_muted_stream_state(sub);
    stream_edit.update_muting_rendering(sub);
    stream_list.set_in_home_view(sub.stream_id, !sub.is_muted);
}
<|endoftext|>


<commit_before>
if(!Files) var Files = {};

Files.Grid = new Class({
	Implements: [Events, Options],

	options: {
		onClickFolder: $empty,
		onClickFile: $empty,
		onClickImage: $empty,
		onDeleteNode: $empty,
		onSwitchLayout: $empty,
		switcher: false,
		layout: false,
		batch_delete: false,
		icon_size: 200,
		types: null // null for all or array to filter for folder, file and image
	},

	initialize: function(container, options) {
		this.setOptions(options);

		this.nodes = new Hash();
		this.container = document.id(container);

		if (this.options.switcher) {
			this.options.switcher = document.id(this.options.switcher);
		}

		if (this.options.batch_delete) {
			this.options.batch_delete = document.getElement(this.options.batch_delete);
		}

		if (this.options.layout) {
			this.setLayout(this.options.layout);
		}
		this.render();
		this.attachEvents();
	},
	attachEvents: function() {

		var that = this,
			createEvent = function(selector, event_name) {
				that.container.addEvent(selector, function(e) {
					e.stop();
					that.fireEvent(event_name, arguments);
				});
			};
		createEvent('click:relay(.files-folder a.navigate)', 'clickFolder');
		createEvent('click:relay(.files-file a.navigate)', 'clickFile');
		createEvent('click:relay(.files-image a.navigate)', 'clickImage');

		/*
		 * Checkbox events
		 */
		var fireCheck = function(e) {
		    if(e.target.match('a.navigate')) {
		        return;
		    }
			if (e.target.get('tag') == 'input') {
				e.target.setProperty('checked', !e.target.getProperty('checked'));
			};
			var box = e.target.match('.files-node') ? e.target : e.target.getParent('.files-node');
			that.checkNode(box.retrieve('row'));
		};
		this.container.addEvent('click:relay(div.imgOutline)', fireCheck.bind(this));

		/*
		 * Delete events
		 */
		var deleteEvt = function(e) {
			if (e.stop) {
				e.stop();
			}

			var path = e.target.getParent('.files-node').retrieve('path');
			this.erase(path);
		}.bind(this);

		this.container.addEvent('click:relay(.delete-node)', deleteEvt);

		if (this.options.batch_delete) {
			var chain = new Chain(),
				chain_call = function() {
					chain.callChain();
				},
				that = this;

			this.addEvent('afterCheckNode', function() {
				var checked = this.container.getElements('input[type=checkbox]:checked');
				this.options.batch_delete.setProperty('disabled', !checked.length);
			}.bind(this));

			this.options.batch_delete.addEvent('click', function(e) {
				e.stop();

				var checkboxes = this.container.getElements('input[type=checkbox]:checked.files-select');

				if (!checkboxes.length || !confirm('There are '+checkboxes.length+' files and folders to be deleted. Are you sure?')) {
					return false;
				}

				that.addEvent('afterDeleteNode', chain_call);
				that.addEvent('afterDeleteNodeFail', chain_call);

				checkboxes.each(function(el) {
					if (!el.checked) {
						return;
					}
					chain.chain(function() {
						deleteEvt({target: el});
					});
				});
				chain.chain(function() {
					that.removeEvent('afterDeleteNode', chain_call);
					that.removeEvent('afterDeleteNodeFail', chain_call);
					chain.clearChain();
				});
				chain.callChain();
			}.bind(this));
		}

		if (this.options.switcher) {
			var that = this;
			this.options.switcher.addEvent('change', function(e) {
				e.stop();

				var value = this.get('value');
				that.setLayout(value);
			});
		}

		if (this.options.icon_size) {
			var size = this.options.icon_size;
			this.addEvent('beforeRenderObject', function(context) {
				context.object.icon_size = size;
			});
		}
	},
	/**
	 * fire_events is used when switching layouts so that client events to
	 * catch the user interactions don't get messed up
	 */
	checkNode: function(row, fire_events) {
		var box = row.element,
			checkbox = box.getElement('input[type=checkbox]')
			;
		if (fire_events !== false) {
			this.fireEvent('beforeCheckNode', {row: row, checkbox: checkbox});
		}

		var old = checkbox.getProperty('checked');
        !old ? box.addClass('selected') : box.removeClass('selected');
		row.checked = !old;
		checkbox.setProperty('checked', !old);

		if (fire_events !== false) {
			this.fireEvent('afterCheckNode', {row: row, checkbox: checkbox});
		}

	},
	erase: function(node) {
		if (typeof node === 'string') {
			node = this.nodes.get(node);
		}
		if (node) {
			this.fireEvent('beforeDeleteNode', {node: node});
			var success = function() {
				if (node.element) {
					node.element.dispose();
				}

				this.nodes.erase(node.path);

				this.fireEvent('afterDeleteNode', {node: node});
			}.bind(this),
				failure = function() {
					this.fireEvent('afterDeleteNodeFail', {node: node});
				}.bind(this);
			node['delete'](success, failure);
		}
	},
	render: function() {
		this.fireEvent('beforeRender');

		this.container.empty();
		this.root = new Files.Grid.Root();
		this.root.element.injectInside(this.container);

		this.renew();

		this.fireEvent('afterRender');
	},
	renderObject: function(object, position) {
		var position = position || 'alphabetical';

		this.fireEvent('beforeRenderObject', {object: object, position: position});

		object.element = object.render();
		object.element.store('path', object.path);
		object.element.store('row', object);

		if (position == 'last') {
			this.root.adopt(object.element, 'bottom');
		}
		else if (position == 'first') {
			this.root.adopt(object.element);
		}
		else {
			var index = this.nodes.filter(function(node){
				return node.type == object.type;
			}).getKeys();

			if (index.length === 0) {
				if (object.type === 'folder') {
					var keys = this.nodes.getKeys();
					if (keys.length) {
						// there are files so append it before the first file
						var target = this.nodes.get(keys[0]);
						object.element.inject(target.element, 'before');
					}
					else {
						this.root.adopt(object.element, 'bottom');
					}
				}
				else {
					this.root.adopt(object.element, 'bottom');
				}

			}
			else {
				index.push(object.path);
				index = index.sort();

				var obj_index = index.indexOf(object.path);
				var length = index.length;
				if (obj_index === 0) {
					var target = this.nodes.get(index[1]);
					object.element.inject(target.element, 'before');
				}
				else {
					var target = obj_index+1 === length ? index[length-2] : index[obj_index-1];
					target = this.nodes.get(target);
					object.element.inject(target.element, 'after');
				}
			}
		}

		this.fireEvent('afterRenderObject', {object: object, position: position});

		return object.element;
	},
	reset: function() {
		this.fireEvent('beforeReset');

		this.nodes.each(function(node) {
			if (node.element) {
				node.element.dispose();
			}
			this.nodes.erase(node.path);
		}.bind(this));

		this.fireEvent('afterReset');
	},
	insert: function(object, position) {
		this.fireEvent('beforeInsertNode', {object: object, position: position});

		if (!this.options.types || this.options.types.contains(object.type)) {
			this.renderObject(object, position);
			this.nodes.set(object.path, object);

			if (this.options.icon_size) {
				this.setIconSize(this.options.icon_size);
			}

			this.fireEvent('afterInsertNode', {node: object, position: position});
		}
	},
	/**
	 * Insert multiple rows, possibly coming from a JSON request
	 */
	insertRows: function(rows) {
		this.fireEvent('beforeInsertRows', {rows: rows});

		$each(rows, function(row) {
			var cls = Files[row.type.capitalize()];
			var item = new cls(row);
			this.insert(item, 'last');
		}.bind(this));

		this.fireEvent('afterInsertRows', {rows: rows});
	},
	renew: function() {
		this.fireEvent('beforeRenew');

		var folders = this.getFolders(),
			files = this.getFiles(),
			that = this,
			renew = function(node) {
				var node = that.nodes.get(node);

				if (node.element) {
					node.element.dispose();
				}
				that.renderObject(node, 'last');

				if (node.checked) {
					that.checkNode(node, false);
				}
			};
		folders.each(renew);
		files.each(renew);

		this.fireEvent('afterRenew');
	},
	setLayout: function(layout) {
		if (layout) {
			this.fireEvent('beforeSetLayout', {layout: layout});

			Files.Template.layout = layout;
			if (this.options.switcher) {
				this.options.switcher.set('value', layout);
			}

			this.fireEvent('afterSetLayout', {layout: layout});

			this.render();
		}

	},
	getFolders: function() {
		return this.nodes.filter(function(node) {
			return node.type === 'folder';
		}).getKeys().sort();
	},
	getFiles: function() {
		return this.nodes.filter(function(node) {
			return node.type === 'file' || node.type == 'image';
		}).getKeys().sort();
	},
	setIconSize: function(size) {
		this.fireEvent('beforeSetIconSize', {size: size});

		this.options.icon_size = size;

		if (this.nodes.getKeys().length) {
			this.container.getElements('.imgTotal').setStyles({
	            width: size + 'px',
	            height: (size * 0.75) + 'px'
	        });
	        this.container.getElements('.imgOutline .ellipsis').setStyle('width', size + 'px');

	        var grid_size = this.container.getSize().x,
	        	item_size = this.container.getElement('.imgOutline').getSize().x + 10,
	        	count = parseInt(grid_size/item_size),
				empty = grid_size - (count*item_size)
	        	;
	    	if (empty < count*10) {
	        	count--;
	        	empty = grid_size - (count*(item_size));
	    	}
	    	var margin = empty/(2*count);
	    	if (margin < 5) {
	        	margin = 5;
	    	}
	    	this.container.getElements('.imgOutline')
	    		.setStyle('margin-left', margin)
	    		.setStyle('margin-right', margin);

		}

    	this.fireEvent('afterSetIconSize', {size: size});
	}
});

Files.Grid.Root = new Class({
	Implements: Files.Template,
	template: 'container',
	initialize: function() {
		this.element = this.render();
	},
	adopt: function(element, position) {
		position = position || 'top';
		var parent = this.element;
		if (this.element.get('tag') == 'table') {
			parent = this.element.getElement('tbody');
		}
		element.injectInside(parent, position);
	}
});<commit_msg>Only set icon sizes in icons layout<commit_after>
if(!Files) var Files = {};

Files.Grid = new Class({
	Implements: [Events, Options],

	options: {
		onClickFolder: $empty,
		onClickFile: $empty,
		onClickImage: $empty,
		onDeleteNode: $empty,
		onSwitchLayout: $empty,
		switcher: false,
		layout: false,
		batch_delete: false,
		icon_size: 200,
		types: null // null for all or array to filter for folder, file and image
	},

	initialize: function(container, options) {
		this.setOptions(options);

		this.nodes = new Hash();
		this.container = document.id(container);

		if (this.options.switcher) {
			this.options.switcher = document.id(this.options.switcher);
		}

		if (this.options.batch_delete) {
			this.options.batch_delete = document.getElement(this.options.batch_delete);
		}

		if (this.options.layout) {
			this.setLayout(this.options.layout);
		}
		this.render();
		this.attachEvents();
	},
	attachEvents: function() {

		var that = this,
			createEvent = function(selector, event_name) {
				that.container.addEvent(selector, function(e) {
					e.stop();
					that.fireEvent(event_name, arguments);
				});
			};
		createEvent('click:relay(.files-folder a.navigate)', 'clickFolder');
		createEvent('click:relay(.files-file a.navigate)', 'clickFile');
		createEvent('click:relay(.files-image a.navigate)', 'clickImage');

		/*
		 * Checkbox events
		 */
		var fireCheck = function(e) {
		    if(e.target.match('a.navigate')) {
		        return;
		    }
			if (e.target.get('tag') == 'input') {
				e.target.setProperty('checked', !e.target.getProperty('checked'));
			};
			var box = e.target.match('.files-node') ? e.target : e.target.getParent('.files-node');
			that.checkNode(box.retrieve('row'));
		};
		this.container.addEvent('click:relay(div.imgOutline)', fireCheck.bind(this));

		/*
		 * Delete events
		 */
		var deleteEvt = function(e) {
			if (e.stop) {
				e.stop();
			}

			var path = e.target.getParent('.files-node').retrieve('path');
			this.erase(path);
		}.bind(this);

		this.container.addEvent('click:relay(.delete-node)', deleteEvt);

		if (this.options.batch_delete) {
			var chain = new Chain(),
				chain_call = function() {
					chain.callChain();
				},
				that = this;

			this.addEvent('afterCheckNode', function() {
				var checked = this.container.getElements('input[type=checkbox]:checked');
				this.options.batch_delete.setProperty('disabled', !checked.length);
			}.bind(this));

			this.options.batch_delete.addEvent('click', function(e) {
				e.stop();

				var checkboxes = this.container.getElements('input[type=checkbox]:checked.files-select');

				if (!checkboxes.length || !confirm('There are '+checkboxes.length+' files and folders to be deleted. Are you sure?')) {
					return false;
				}

				that.addEvent('afterDeleteNode', chain_call);
				that.addEvent('afterDeleteNodeFail', chain_call);

				checkboxes.each(function(el) {
					if (!el.checked) {
						return;
					}
					chain.chain(function() {
						deleteEvt({target: el});
					});
				});
				chain.chain(function() {
					that.removeEvent('afterDeleteNode', chain_call);
					that.removeEvent('afterDeleteNodeFail', chain_call);
					chain.clearChain();
				});
				chain.callChain();
			}.bind(this));
		}

		if (this.options.switcher) {
			var that = this;
			this.options.switcher.addEvent('change', function(e) {
				e.stop();

				var value = this.get('value');
				that.setLayout(value);
			});
		}

		if (this.options.icon_size) {
			var size = this.options.icon_size;
			this.addEvent('beforeRenderObject', function(context) {
				context.object.icon_size = size;
			});
		}
	},
	/**
	 * fire_events is used when switching layouts so that client events to
	 * catch the user interactions don't get messed up
	 */
	checkNode: function(row, fire_events) {
		var box = row.element,
			checkbox = box.getElement('input[type=checkbox]')
			;
		if (fire_events !== false) {
			this.fireEvent('beforeCheckNode', {row: row, checkbox: checkbox});
		}

		var old = checkbox.getProperty('checked');
        !old ? box.addClass('selected') : box.removeClass('selected');
		row.checked = !old;
		checkbox.setProperty('checked', !old);

		if (fire_events !== false) {
			this.fireEvent('afterCheckNode', {row: row, checkbox: checkbox});
		}

	},
	erase: function(node) {
		if (typeof node === 'string') {
			node = this.nodes.get(node);
		}
		if (node) {
			this.fireEvent('beforeDeleteNode', {node: node});
			var success = function() {
				if (node.element) {
					node.element.dispose();
				}

				this.nodes.erase(node.path);

				this.fireEvent('afterDeleteNode', {node: node});
			}.bind(this),
				failure = function() {
					this.fireEvent('afterDeleteNodeFail', {node: node});
				}.bind(this);
			node['delete'](success, failure);
		}
	},
	render: function() {
		this.fireEvent('beforeRender');

		this.container.empty();
		this.root = new Files.Grid.Root();
		this.root.element.injectInside(this.container);

		this.renew();

		this.fireEvent('afterRender');
	},
	renderObject: function(object, position) {
		var position = position || 'alphabetical';

		this.fireEvent('beforeRenderObject', {object: object, position: position});

		object.element = object.render();
		object.element.store('path', object.path);
		object.element.store('row', object);

		if (position == 'last') {
			this.root.adopt(object.element, 'bottom');
		}
		else if (position == 'first') {
			this.root.adopt(object.element);
		}
		else {
			var index = this.nodes.filter(function(node){
				return node.type == object.type;
			}).getKeys();

			if (index.length === 0) {
				if (object.type === 'folder') {
					var keys = this.nodes.getKeys();
					if (keys.length) {
						// there are files so append it before the first file
						var target = this.nodes.get(keys[0]);
						object.element.inject(target.element, 'before');
					}
					else {
						this.root.adopt(object.element, 'bottom');
					}
				}
				else {
					this.root.adopt(object.element, 'bottom');
				}

			}
			else {
				index.push(object.path);
				index = index.sort();

				var obj_index = index.indexOf(object.path);
				var length = index.length;
				if (obj_index === 0) {
					var target = this.nodes.get(index[1]);
					object.element.inject(target.element, 'before');
				}
				else {
					var target = obj_index+1 === length ? index[length-2] : index[obj_index-1];
					target = this.nodes.get(target);
					object.element.inject(target.element, 'after');
				}
			}
		}

		this.fireEvent('afterRenderObject', {object: object, position: position});

		return object.element;
	},
	reset: function() {
		this.fireEvent('beforeReset');

		this.nodes.each(function(node) {
			if (node.element) {
				node.element.dispose();
			}
			this.nodes.erase(node.path);
		}.bind(this));

		this.fireEvent('afterReset');
	},
	insert: function(object, position) {
		this.fireEvent('beforeInsertNode', {object: object, position: position});

		if (!this.options.types || this.options.types.contains(object.type)) {
			this.renderObject(object, position);
			this.nodes.set(object.path, object);

			if (this.options.icon_size) {
				this.setIconSize(this.options.icon_size);
			}

			this.fireEvent('afterInsertNode', {node: object, position: position});
		}
	},
	/**
	 * Insert multiple rows, possibly coming from a JSON request
	 */
	insertRows: function(rows) {
		this.fireEvent('beforeInsertRows', {rows: rows});

		$each(rows, function(row) {
			var cls = Files[row.type.capitalize()];
			var item = new cls(row);
			this.insert(item, 'last');
		}.bind(this));

		this.fireEvent('afterInsertRows', {rows: rows});
	},
	renew: function() {
		this.fireEvent('beforeRenew');

		var folders = this.getFolders(),
			files = this.getFiles(),
			that = this,
			renew = function(node) {
				var node = that.nodes.get(node);

				if (node.element) {
					node.element.dispose();
				}
				that.renderObject(node, 'last');

				if (node.checked) {
					that.checkNode(node, false);
				}
			};
		folders.each(renew);
		files.each(renew);

		this.fireEvent('afterRenew');
	},
	setLayout: function(layout) {
		if (layout) {
			this.fireEvent('beforeSetLayout', {layout: layout});

			Files.Template.layout = layout;
			if (this.options.switcher) {
				this.options.switcher.set('value', layout);
			}

			this.fireEvent('afterSetLayout', {layout: layout});

			this.render();
		}

	},
	getFolders: function() {
		return this.nodes.filter(function(node) {
			return node.type === 'folder';
		}).getKeys().sort();
	},
	getFiles: function() {
		return this.nodes.filter(function(node) {
			return node.type === 'file' || node.type == 'image';
		}).getKeys().sort();
	},
	setIconSize: function(size) {
		this.fireEvent('beforeSetIconSize', {size: size});

		this.options.icon_size = size;

		if (this.nodes.getKeys().length && Files.Template.layout == 'icons') {
			this.container.getElements('.imgTotal').setStyles({
	            width: size + 'px',
	            height: (size * 0.75) + 'px'
	        });
	        this.container.getElements('.imgOutline .ellipsis').setStyle('width', size + 'px');

	        var grid_size = this.container.getSize().x,
	        	item_size = this.container.getElement('.imgOutline').getSize().x + 10,
	        	count = parseInt(grid_size/item_size),
				empty = grid_size - (count*item_size)
	        	;
	    	if (empty < count*10) {
	        	count--;
	        	empty = grid_size - (count*(item_size));
	    	}
	    	var margin = empty/(2*count);
	    	if (margin < 5) {
	        	margin = 5;
	    	}
	    	this.container.getElements('.imgOutline')
	    		.setStyle('margin-left', margin)
	    		.setStyle('margin-right', margin);

		}

    	this.fireEvent('afterSetIconSize', {size: size});
	}
});

Files.Grid.Root = new Class({
	Implements: Files.Template,
	template: 'container',
	initialize: function() {
		this.element = this.render();
	},
	adopt: function(element, position) {
		position = position || 'top';
		var parent = this.element;
		if (this.element.get('tag') == 'table') {
			parent = this.element.getElement('tbody');
		}
		element.injectInside(parent, position);
	}
});<|endoftext|>


<commit_before>/*
 Copyright 2013 Daniel Wirtz <dcode@dcode.io>

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
var description = "Plain .proto descriptor";

var ProtoBuf = require(__dirname+"/../../../index.js"),
    util = require("../util.js");

/**
 * pbjs target: Plain .proto descriptor
 * @exports pbjs/targets/proto
 * @function
 * @param {!ProtoBuf.Builder} builder Builder
 * @param {!Object.<string,*>=} options Options
 * @returns {string}
 */
var proto = module.exports = function(builder, options) {
    options = options || {};
    builder.resolveAll();

    // Set the pointer to the lowest common namespace (with options)
    var ptr = builder.ns;
    while (ptr.children.length === 1 && Object.keys(ptr.options).length === 0 && ptr.children[0].className === "Namespace")
        ptr = ptr.children[0];

    var out = [];

    function trim() {
        out[out.length-1] = out[out.length-1].replace(/\n{2,}$/, "\n");
    }

    // Builds a set of top level options
    function buildOptions(opt, indent) {
        var keys;
        if ((keys = Object.keys(opt)).length === 0)
            return;
        keys.forEach(function(key) {
            if (!options.min)
                out.push(indent);
            out.push("option ", key, options.min ? "=" : " = ", value(opt[key]), options.min ? ";" : ";\n");
        });
        if (!options.min)
            out[out.length-1] += "\n";
    }

    // Builds everything within a namespace
    function buildNamespace(ns, indent) {
        ns.getChildren(ProtoBuf.Reflect.Enum).forEach(function(enm) {
            buildEnum(enm, indent);
        });
        ns.getChildren(ProtoBuf.Reflect.Message).forEach(function(msg) {
            buildMessage(msg, indent);
        });
        var exts = util.groupExtensions(ns);
        if (exts !== null) {
            Object.keys(exts).forEach(function(extFqn) {
                var extMsg = ns.resolve(extFqn),
                    extFields = exts[extFqn];
                if (!options.min)
                    out.push(indent);
                out.push("extend ", ns.qn(extMsg), options.min ? "{" : " {\n");
                extFields.forEach(function(extField) {
                    buildMessageField(ns, extField, indent+"    ", false);
                });
                if (!options.min)
                    out.push(indent);
                out.push(options.min ? "}" : "}\n\n");
            });
        }
        ns.getChildren(ProtoBuf.Reflect.Service).forEach(function(svc) {
            buildService(svc, indent);
        });
        ns.getChildren(ProtoBuf.Reflect.Namespace).forEach(function(innerNs) {
            if (innerNs.className !== "Namespace")
                return;
            if (!options.min)
                out.push(indent);
            out.push("message ", innerNs.name, options.min ? "{" : " {\n");
            buildNamespace(innerNs, indent+"    ");
            if (!options.min)
                out.push(indent);
            out.push(options.min ? "}" : "}\n");
        });
        trim();
    }

    // Builds a message
    function buildMessage(msg, indent) {
        if (!options.min)
            out.push(indent);
        out.push("message ", msg.name, options.min ? "{" : " {\n");
        buildOptions(msg.options, indent+"    ");
        var n = 0, oneofFields = [];
        msg.getChildren(ProtoBuf.Reflect.Message.OneOf).forEach(function(oneof) {
            if (!options.min)
                out.push(indent, "    ");
            out.push("oneof ", oneof.name, options.min ? "{" : " {\n");
            oneof.fields.forEach(function(fld) {
                buildMessageField(msg, fld, indent+"        ", true);
                oneofFields.push(fld);
            });
            if (!options.min)
                out.push(indent, "    ");
            out.push(options.min ? "}" : "}\n");
        });
        msg.getChildren(ProtoBuf.Reflect.Message.Field).forEach(function(fld) {
            if (fld instanceof ProtoBuf.Reflect.Message.ExtensionField)
                return;
            if (oneofFields.indexOf(fld) >= 0)
                return;
            buildMessageField(msg, fld, indent+"    ", false);
            n++;
        });
        if (n > 0 && !options.min)
            out[out.length-1] += "\n";
        if (msg.extensions[0] !== ProtoBuf.ID_MIN || msg.extensions[1] !== ProtoBuf.ID_MAX) {
            if (!options.min)
                out.push(indent, "    ");
            out.push("extensions ", value(msg.extensions[0]), " to ", msg.extensions[1] === ProtoBuf.ID_MAX ? "max" : value(msg.extensions[1]), options.min ? ";" : ";\n\n");
        }
        buildNamespace(msg, indent+"    ");
        if (!options.min)
            out.push(indent);
        out.push(options.min ? "}" : "}\n\n");
    }

    // Builds a message field
    function buildMessageField(msg, fld, indent, isOneOf) {
        if (!options.min)
            out.push(indent);
        if (!isOneOf)
            out.push(fld.required ? "required " : (fld.repeated ? "repeated " : "optional "));
        if (fld.resolvedType !== null)
            out.push(msg.qn(fld.resolvedType));
        else
            out.push(fld.type['name']);
        out.push(" ", fld instanceof ProtoBuf.Reflect.Message.ExtensionField ? fld.name.substring(fld.name.lastIndexOf(".")+1) : fld.name, options.min ? "=" : " = ", fld.id);
        var keys = Object.keys(fld.options);
        if (keys.length > 0) {
            out.push(options.min ? "[" : " [");
            var n = 0;
            keys.forEach(function(key) {
                if (n > 0)
                    out.push(options.min ? "," : ", ");
                out.push(key, options.min ? "=" : " = ",
                    // BEWARE: Monkey patch for string enum defaults
                    key === "default" && fld.type === ProtoBuf.TYPES["enum"] && typeof fld.options[key] === 'string' ? fld.options[key] : value(fld.options[key])
                );
                n++;
            });
            out.push("]");
        }
        out.push(options.min ? ";" : ";\n");
    }

    // Builds an enum
    function buildEnum(enm, indent) {
        if (!options.min)
            out.push(indent);
        out.push("enum ", enm.name, options.min ? "{" : " {\n");
        buildOptions(enm.options, indent+"    ");
        enm.getChildren(ProtoBuf.Reflect.Enum.Value).forEach(function(val) {
            if (!options.min)
                out.push(indent, "    ");
            out.push(val.name, options.min ? "=" : " = ", val.id, options.min? ";" : ";\n");
        });
        if (!options.min)
            out.push(indent);
        out.push(options.min ? "}" : "}\n\n");
    }

    // Builds a service
    function buildService(svc, indent) {
        if (!options.min)
            out.push(indent);
        out.push("service ", svc.name, options.min ? "{" : " {\n");
        buildOptions(svc.options, indent+"    ");
        svc.getChildren(ProtoBuf.Reflect.Service.RPCMethod).forEach(function(rpc) {
            if (!options.min)
                out.push(indent+"    ");
            out.push("rpc ", rpc.name, "(", svc.qn(rpc.resolvedRequestType), ") returns(", svc.qn(rpc.resolvedResponseType), ")");
            var keys = Object.keys(rpc.options);
            if (keys.length === 0) {
                out.push(options.min ? ";" : ";\n")
            } else {
                out.push(options.min ? "{" : " {\n");
                buildOptions(rpc.options, indent+"        ");
                trim();
                if (!options.min)
                    out.push(indent+"    ");
                out.push(options.min ? "}" : "}\n");
            }
            if (!options.min)
                out[out.length-1] += "\n";
        });
        trim();
        out.push(options.min ? "}" : "}\n");
    }

    // Start by building the package namespace
    var pkg = ptr.fqn().substring(1);
    if (pkg !== "")
        out.push("package ", pkg, options.min ? ";" : ";\n\n");
    buildOptions(ptr.options, "");
    buildNamespace(ptr, "");
    return out.join('');
};

/**
 * Module description.
 * @type {string}
 */
proto.description = description;

/**
 * Converts a JavaScript value to a .proto value.
 * @param {*} v Value
 * @returns {string} Dot proto value
 */
function value(v) {
    switch (typeof v) {
        case 'boolean':
            return v ? 'true' : 'false';
        case 'number':
            return v.toString();
        case 'string':
            return '"'+v.replace(/"/g, '\\"')+'"';
        default:
            throw new Error("illegal value type: "+typeof(v));
    }
}
<commit_msg>Properly reconstruct legacy groups in pbjs proto target, fixes #355<commit_after>/*
 Copyright 2013 Daniel Wirtz <dcode@dcode.io>

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
var description = "Plain .proto descriptor";

var ProtoBuf = require(__dirname+"/../../../index.js"),
    util = require("../util.js");

/**
 * pbjs target: Plain .proto descriptor
 * @exports pbjs/targets/proto
 * @function
 * @param {!ProtoBuf.Builder} builder Builder
 * @param {!Object.<string,*>=} options Options
 * @returns {string}
 */
var proto = module.exports = function(builder, options) {
    options = options || {};
    builder.resolveAll();

    // Set the pointer to the lowest common namespace (with options)
    var ptr = builder.ns;
    while (ptr.children.length === 1 && Object.keys(ptr.options).length === 0 && ptr.children[0].className === "Namespace")
        ptr = ptr.children[0];

    var out = [];

    function trim() {
        out[out.length-1] = out[out.length-1].replace(/\n{2,}$/, "\n");
    }

    // Builds a set of top level options
    function buildOptions(opt, indent) {
        var keys;
        if ((keys = Object.keys(opt)).length === 0)
            return;
        keys.forEach(function(key) {
            if (!options.min)
                out.push(indent);
            out.push("option ", key, options.min ? "=" : " = ", value(opt[key]), options.min ? ";" : ";\n");
        });
        if (!options.min)
            out[out.length-1] += "\n";
    }

    // Builds everything within a namespace
    function buildNamespace(ns, indent) {
        ns.getChildren(ProtoBuf.Reflect.Enum).forEach(function(enm) {
            buildEnum(enm, indent);
        });
        ns.getChildren(ProtoBuf.Reflect.Message).forEach(function(msg) {
            if (!msg.isGroup) // legacy groups are build within the respective field
                buildMessage(msg, indent);
        });
        var exts = util.groupExtensions(ns);
        if (exts !== null) {
            Object.keys(exts).forEach(function(extFqn) {
                var extMsg = ns.resolve(extFqn),
                    extFields = exts[extFqn];
                if (!options.min)
                    out.push(indent);
                out.push("extend ", ns.qn(extMsg), options.min ? "{" : " {\n");
                extFields.forEach(function(extField) {
                    buildMessageField(ns, extField, indent+"    ", false);
                });
                if (!options.min)
                    out.push(indent);
                out.push(options.min ? "}" : "}\n\n");
            });
        }
        ns.getChildren(ProtoBuf.Reflect.Service).forEach(function(svc) {
            buildService(svc, indent);
        });
        ns.getChildren(ProtoBuf.Reflect.Namespace).forEach(function(innerNs) {
            if (innerNs.className !== "Namespace")
                return;
            if (!options.min)
                out.push(indent);
            out.push("message ", innerNs.name, options.min ? "{" : " {\n");
            buildNamespace(innerNs, indent+"    ");
            if (!options.min)
                out.push(indent);
            out.push(options.min ? "}" : "}\n");
        });
        trim();
    }

    // Builds a message
    function buildMessage(msg, indent) {
        if (!msg.isGroup) {
            if (!options.min)
                out.push(indent);
            out.push("message ", msg.name);
        }
        out.push(options.min ? "{" : " {\n");
        buildOptions(msg.options, indent+"    ");
        var n = 0, oneofFields = [];
        msg.getChildren(ProtoBuf.Reflect.Message.OneOf).forEach(function(oneof) {
            if (!options.min)
                out.push(indent, "    ");
            out.push("oneof ", oneof.name, options.min ? "{" : " {\n");
            oneof.fields.forEach(function(fld) {
                buildMessageField(msg, fld, indent+"        ", true);
                oneofFields.push(fld);
            });
            if (!options.min)
                out.push(indent, "    ");
            out.push(options.min ? "}" : "}\n");
        });
        msg.getChildren(ProtoBuf.Reflect.Message.Field).forEach(function(fld) {
            if (fld instanceof ProtoBuf.Reflect.Message.ExtensionField)
                return;
            if (oneofFields.indexOf(fld) >= 0)
                return;
            buildMessageField(msg, fld, indent+"    ", false);
            n++;
        });
        if (n > 0 && !options.min)
            out[out.length-1] += "\n";
        if (msg.extensions[0] !== ProtoBuf.ID_MIN || msg.extensions[1] !== ProtoBuf.ID_MAX) {
            if (!options.min)
                out.push(indent, "    ");
            out.push("extensions ", value(msg.extensions[0]), " to ", msg.extensions[1] === ProtoBuf.ID_MAX ? "max" : value(msg.extensions[1]), options.min ? ";" : ";\n\n");
        }
        buildNamespace(msg, indent+"    ");
        if (!options.min)
            out.push(indent);
        out.push(options.min ? "}" : "}\n\n");
    }

    // Builds a message field
    function buildMessageField(msg, fld, indent, isOneOf) {
        var isGroup = false;
        if (!options.min)
            out.push(indent);
        if (!isOneOf)
            out.push(fld.required ? "required " : (fld.repeated ? "repeated " : "optional "));
        if (fld.resolvedType !== null) {
            if (fld.resolvedType instanceof ProtoBuf.Reflect.Message && fld.resolvedType.isGroup) {
                out.push("group ", msg.qn(fld.resolvedType));
                isGroup = true;
            } else
                out.push(msg.qn(fld.resolvedType));
        } else
            out.push(fld.type['name']);
        if (!isGroup)
            out.push(" ", fld instanceof ProtoBuf.Reflect.Message.ExtensionField ? fld.name.substring(fld.name.lastIndexOf(".")+1) : fld.name);
        out.push(options.min ? "=" : " = ", fld.id);
        if (isGroup)
            buildMessage(fld.resolvedType, indent);
        else {
            var keys = Object.keys(fld.options);
            if (keys.length > 0) {
                out.push(options.min ? "[" : " [");
                var n = 0;
                keys.forEach(function (key) {
                    if (n > 0)
                        out.push(options.min ? "," : ", ");
                    out.push(key, options.min ? "=" : " = ",
                        // BEWARE: Monkey patch for string enum defaults
                        key === "default" && fld.type === ProtoBuf.TYPES["enum"] && typeof fld.options[key] === 'string' ? fld.options[key] : value(fld.options[key])
                    );
                    n++;
                });
                out.push("]");
            }
            out.push(options.min ? ";" : ";\n");
        }
    }

    // Builds an enum
    function buildEnum(enm, indent) {
        if (!options.min)
            out.push(indent);
        out.push("enum ", enm.name, options.min ? "{" : " {\n");
        buildOptions(enm.options, indent+"    ");
        enm.getChildren(ProtoBuf.Reflect.Enum.Value).forEach(function(val) {
            if (!options.min)
                out.push(indent, "    ");
            out.push(val.name, options.min ? "=" : " = ", val.id, options.min? ";" : ";\n");
        });
        if (!options.min)
            out.push(indent);
        out.push(options.min ? "}" : "}\n\n");
    }

    // Builds a service
    function buildService(svc, indent) {
        if (!options.min)
            out.push(indent);
        out.push("service ", svc.name, options.min ? "{" : " {\n");
        buildOptions(svc.options, indent+"    ");
        svc.getChildren(ProtoBuf.Reflect.Service.RPCMethod).forEach(function(rpc) {
            if (!options.min)
                out.push(indent+"    ");
            out.push("rpc ", rpc.name, "(", svc.qn(rpc.resolvedRequestType), ") returns(", svc.qn(rpc.resolvedResponseType), ")");
            var keys = Object.keys(rpc.options);
            if (keys.length === 0) {
                out.push(options.min ? ";" : ";\n")
            } else {
                out.push(options.min ? "{" : " {\n");
                buildOptions(rpc.options, indent+"        ");
                trim();
                if (!options.min)
                    out.push(indent+"    ");
                out.push(options.min ? "}" : "}\n");
            }
            if (!options.min)
                out[out.length-1] += "\n";
        });
        trim();
        out.push(options.min ? "}" : "}\n");
    }

    // Start by building the package namespace
    var pkg = ptr.fqn().substring(1);
    if (pkg !== "")
        out.push("package ", pkg, options.min ? ";" : ";\n\n");
    buildOptions(ptr.options, "");
    buildNamespace(ptr, "");
    return out.join('');
};

/**
 * Module description.
 * @type {string}
 */
proto.description = description;

/**
 * Converts a JavaScript value to a .proto value.
 * @param {*} v Value
 * @returns {string} Dot proto value
 */
function value(v) {
    switch (typeof v) {
        case 'boolean':
            return v ? 'true' : 'false';
        case 'number':
            return v.toString();
        case 'string':
            return '"'+v.replace(/"/g, '\\"')+'"';
        default:
            throw new Error("illegal value type: "+typeof(v));
    }
}
<|endoftext|>


<commit_before>/* jshint -W070 */
'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to match all subfolders:
// 'test/spec/**/*.js'
// templateFramework: 'lodash'

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dist: 'dist',
        docs: 'docs'
    };

    grunt.initConfig({
        yeoman: yeomanConfig,
        watch: {
            coffee: {
                files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
                tasks: ['newer:coffee:dist']
            },
            coffeeTest: {
                files: ['test/spec/{,*/}*.coffee'],
                tasks: ['newer:coffee:test']
            },
            compass: {
                config: 'config.rb',
                files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
                tasks: ['compass']
            },
            livereload: {
                files: [
                    '<%= yeoman.app %>/*.html',
                    '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
                    '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                    '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}'
                ],
                tasks: ['livereload']
            },
            jst: {
                files: [
                    '<%= yeoman.app %>/scripts/templates/*.ejs',
                    '<%= yeoman.app %>/scripts/templates/graphite/*.ejs',
                ],
                tasks: ['jst']
            }
        },
        connect: {
            options: {
                port: 9000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: '0.0.0.0'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'app')
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test')
                        ];
                    }
                }
            },
            dist: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, 'dist')
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: ['.tmp', '<%= yeoman.dist %>/*'],
            server: '.tmp'
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                'Gruntfile.js',
                '<%= yeoman.app %>/scripts/{,*/}*.js',
                '!<%= yeoman.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://localhost:<%= connect.options.port %>/index.html']
                }
            }
        },
        coffee: {
            dist: {
                files: [{
                    // rather than compiling multiple files here you should
                    // require them into your main .coffee file
                    expand: true,
                    cwd: '<%= yeoman.app %>/scripts',
                    src: '*.coffee',
                    dest: '.tmp/scripts',
                    ext: '.js'
                }]
            },
            test: {
                files: [{
                    expand: true,
                    cwd: '.tmp/spec',
                    src: '*.coffee',
                    dest: 'test/spec'
                }]
            }
        },
        compass: {
            options: {
                sassDir: '<%= yeoman.app %>/styles',
                cssDir: '.tmp/styles',
                imagesDir: '<%= yeoman.app %>/images',
                javascriptsDir: '<%= yeoman.app %>/scripts',
                fontsDir: '<%= yeoman.app %>/styles/fonts',
                importPath: 'app/bower_components',
                relativeAssets: true
            },
            dist: {},
            server: {
                options: {
                    debugInfo: true
                }
            }
        },
        requirejs: {
            dist: {
                // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
                options: {
                    // `name` and `out` is set by grunt-usemin
                    baseUrl: 'app/scripts',
                    optimize: 'none',
                    paths: {
                        'templates': '../../.tmp/scripts/templates'
                    },
                    // TODO: Figure out how to make sourcemaps work with grunt-usemin
                    // https://github.com/yeoman/grunt-usemin/issues/30
                    //generateSourceMaps: true,
                    // required to support SourceMaps
                    // http://requirejs.org/docs/errors.html#sourcemapcomments
                    preserveLicenseComments: false,
                    useStrict: true,
                    wrap: true,
                    //uglify2: {} // https://github.com/mishoo/UglifyJS2
                }
            }
        },
        useminPrepare: {
            html: '<%= yeoman.app %>/index.html',
            options: {
                dest: '<%= yeoman.dist %>'
            }
        },
        usemin: {
            html: ['<%= yeoman.dist %>/{,*/}*.html'],
            css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
            options: {
                dirs: ['<%= yeoman.dist %>']
            }
        },
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/images',
                    src: '{,*/}*.{png,jpg,jpeg}',
                    dest: '<%= yeoman.dist %>/images'
                }]
            }
        },
        cssmin: {
            dist: {
                files: {
                    '<%= yeoman.dist %>/styles/main.css': [
                        '.tmp/styles/{,*/}*.css',
                        '<%= yeoman.app %>/styles/{,*/}*.css'
                    ]
                }
            }
        },
        htmlmin: {
            dist: {
                options: {
                    /*removeCommentsFromCDATA: true,
                    // https://github.com/yeoman/grunt-usemin/issues/44
                    //collapseWhitespace: true,
                    collapseBooleanAttributes: true,
                    removeAttributeQuotes: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true*/
                },
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>',
                    src: '*.html',
                    dest: '<%= yeoman.dist %>'
                }]
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        '*.{ico,txt}',
                        '.htaccess',
                        'images/{,*/}*.{webp,gif}',
                        'font/*'
                    ]
                }, {
                    expand: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        'styles/*.{woff,otf,eot,svg,ttf}'
                    ]
                }]
            }
        },
        bower: {
            all: {
                rjsConfig: '<%= yeoman.app %>/scripts/main.js'
            }
        },
        jst: {
            options: {
                amd: true
            },
            compile: {
                files: {
                    '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.ejs', '<%= yeoman.app %>/scripts/templates/graphite/*.ejs']
                }
            }
        },
        docco: {
            dist: {
                src: ['<%= yeoman.app %>/scripts/**/*.js'],
                options: {
                    output: '<%= yeoman.docs %>'
                }
            }
        },
        symlink: {
            font: {
                target: 'bower_components/font-awesome/font',
                link: '<%= yeoman.app %>/font',
                options: {
                    overwrite: true,
                    force: true
                }
            }
        },
        'git-describe': {
            options: {
                'failOnError': false
            },
            'git.js': {
            }
        }
    });

    grunt.renameTask('regarde', 'watch');

    grunt.registerTask('createDefaultTemplate', function () {
        grunt.file.write('.tmp/scripts/templates.js', 'this.JST = this.JST || {};');
    });

    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'symlink',
            'clean:server',
            'coffee:dist',
            'createDefaultTemplate',
            'jst',
            'compass:server',
            'livereload-start',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });

    grunt.registerTask('test', [
        'clean:server',
        'symlink',
        'coffee',
        'createDefaultTemplate',
        'jst',
        'compass',
        'connect:test',
        'mocha'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
        'symlink',
        'coffee',
        'createDefaultTemplate',
        'jst',
        'compass:dist',
        'useminPrepare',
        'requirejs',
        'imagemin',
        'htmlmin',
        'concat',
        'cssmin',
        'uglify',
        'copy',
        'usemin'
    ]);
    grunt.registerTask('docs', [
        'docco:dist'
    ]);
    grunt.registerTask('default', [
        'saveRevision',
        'jshint',
        'symlink',
        'test',
        'build',
        'docs'
    ]);
    grunt.registerTask('saveRevision', function() {
        grunt.event.once('git-describe', function(rev) {
            grunt.log.writeln('Git Revision: ' + rev);
            grunt.file.write('app/scripts/git.js', '/* jshint -W105 */\n/* global define */\ndefine([], function() { \'use strict\'; return { \'git-commit\': \'' + rev + '\' }; });');
        });
        grunt.task.run('git-describe');
    });
};
<commit_msg>Remove docco as it causes jenkins to hang<commit_after>/* jshint -W070 */
'use strict';
var lrSnippet = require('grunt-contrib-livereload/lib/utils').livereloadSnippet;
var mountFolder = function (connect, dir) {
    return connect.static(require('path').resolve(dir));
};

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to match all subfolders:
// 'test/spec/**/*.js'
// templateFramework: 'lodash'

module.exports = function (grunt) {
    // load all grunt tasks
    require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);

    // configurable paths
    var yeomanConfig = {
        app: 'app',
        dist: 'dist',
        docs: 'docs'
    };

    grunt.initConfig({
        yeoman: yeomanConfig,
        watch: {
            coffee: {
                files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
                tasks: ['newer:coffee:dist']
            },
            coffeeTest: {
                files: ['test/spec/{,*/}*.coffee'],
                tasks: ['newer:coffee:test']
            },
            compass: {
                config: 'config.rb',
                files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
                tasks: ['compass']
            },
            livereload: {
                files: [
                    '<%= yeoman.app %>/*.html',
                    '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
                    '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                    '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp}'
                ],
                tasks: ['livereload']
            },
            jst: {
                files: [
                    '<%= yeoman.app %>/scripts/templates/*.ejs',
                    '<%= yeoman.app %>/scripts/templates/graphite/*.ejs',
                ],
                tasks: ['jst']
            }
        },
        connect: {
            options: {
                port: 9000,
                // change this to '0.0.0.0' to access the server from outside
                hostname: '0.0.0.0'
            },
            livereload: {
                options: {
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'app')
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test')
                        ];
                    }
                }
            },
            dist: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, 'dist')
                        ];
                    }
                }
            }
        },
        open: {
            server: {
                path: 'http://localhost:<%= connect.options.port %>'
            }
        },
        clean: {
            dist: ['.tmp', '<%= yeoman.dist %>/*'],
            server: '.tmp'
        },
        jshint: {
            options: {
                jshintrc: '.jshintrc'
            },
            all: [
                'Gruntfile.js',
                '<%= yeoman.app %>/scripts/{,*/}*.js',
                '!<%= yeoman.app %>/scripts/vendor/*',
                'test/spec/{,*/}*.js'
            ]
        },
        mocha: {
            all: {
                options: {
                    run: true,
                    urls: ['http://localhost:<%= connect.options.port %>/index.html']
                }
            }
        },
        coffee: {
            dist: {
                files: [{
                    // rather than compiling multiple files here you should
                    // require them into your main .coffee file
                    expand: true,
                    cwd: '<%= yeoman.app %>/scripts',
                    src: '*.coffee',
                    dest: '.tmp/scripts',
                    ext: '.js'
                }]
            },
            test: {
                files: [{
                    expand: true,
                    cwd: '.tmp/spec',
                    src: '*.coffee',
                    dest: 'test/spec'
                }]
            }
        },
        compass: {
            options: {
                sassDir: '<%= yeoman.app %>/styles',
                cssDir: '.tmp/styles',
                imagesDir: '<%= yeoman.app %>/images',
                javascriptsDir: '<%= yeoman.app %>/scripts',
                fontsDir: '<%= yeoman.app %>/styles/fonts',
                importPath: 'app/bower_components',
                relativeAssets: true
            },
            dist: {},
            server: {
                options: {
                    debugInfo: true
                }
            }
        },
        requirejs: {
            dist: {
                // Options: https://github.com/jrburke/r.js/blob/master/build/example.build.js
                options: {
                    // `name` and `out` is set by grunt-usemin
                    baseUrl: 'app/scripts',
                    optimize: 'none',
                    paths: {
                        'templates': '../../.tmp/scripts/templates'
                    },
                    // TODO: Figure out how to make sourcemaps work with grunt-usemin
                    // https://github.com/yeoman/grunt-usemin/issues/30
                    //generateSourceMaps: true,
                    // required to support SourceMaps
                    // http://requirejs.org/docs/errors.html#sourcemapcomments
                    preserveLicenseComments: false,
                    useStrict: true,
                    wrap: true,
                    //uglify2: {} // https://github.com/mishoo/UglifyJS2
                }
            }
        },
        useminPrepare: {
            html: '<%= yeoman.app %>/index.html',
            options: {
                dest: '<%= yeoman.dist %>'
            }
        },
        usemin: {
            html: ['<%= yeoman.dist %>/{,*/}*.html'],
            css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
            options: {
                dirs: ['<%= yeoman.dist %>']
            }
        },
        imagemin: {
            dist: {
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>/images',
                    src: '{,*/}*.{png,jpg,jpeg}',
                    dest: '<%= yeoman.dist %>/images'
                }]
            }
        },
        cssmin: {
            dist: {
                files: {
                    '<%= yeoman.dist %>/styles/main.css': [
                        '.tmp/styles/{,*/}*.css',
                        '<%= yeoman.app %>/styles/{,*/}*.css'
                    ]
                }
            }
        },
        htmlmin: {
            dist: {
                options: {
                    /*removeCommentsFromCDATA: true,
                    // https://github.com/yeoman/grunt-usemin/issues/44
                    //collapseWhitespace: true,
                    collapseBooleanAttributes: true,
                    removeAttributeQuotes: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeOptionalTags: true*/
                },
                files: [{
                    expand: true,
                    cwd: '<%= yeoman.app %>',
                    src: '*.html',
                    dest: '<%= yeoman.dist %>'
                }]
            }
        },
        copy: {
            dist: {
                files: [{
                    expand: true,
                    dot: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        '*.{ico,txt}',
                        '.htaccess',
                        'images/{,*/}*.{webp,gif}',
                        'font/*'
                    ]
                }, {
                    expand: true,
                    cwd: '<%= yeoman.app %>',
                    dest: '<%= yeoman.dist %>',
                    src: [
                        'styles/*.{woff,otf,eot,svg,ttf}'
                    ]
                }]
            }
        },
        bower: {
            all: {
                rjsConfig: '<%= yeoman.app %>/scripts/main.js'
            }
        },
        jst: {
            options: {
                amd: true
            },
            compile: {
                files: {
                    '.tmp/scripts/templates.js': ['<%= yeoman.app %>/scripts/templates/*.ejs', '<%= yeoman.app %>/scripts/templates/graphite/*.ejs']
                }
            }
        },
        docco: {
            dist: {
                src: ['<%= yeoman.app %>/scripts/**/*.js'],
                options: {
                    output: '<%= yeoman.docs %>'
                }
            }
        },
        symlink: {
            font: {
                target: 'bower_components/font-awesome/font',
                link: '<%= yeoman.app %>/font',
                options: {
                    overwrite: true,
                    force: true
                }
            }
        },
        'git-describe': {
            options: {
                'failOnError': false
            },
            'git.js': {
            }
        }
    });

    grunt.renameTask('regarde', 'watch');

    grunt.registerTask('createDefaultTemplate', function () {
        grunt.file.write('.tmp/scripts/templates.js', 'this.JST = this.JST || {};');
    });

    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'symlink',
            'clean:server',
            'coffee:dist',
            'createDefaultTemplate',
            'jst',
            'compass:server',
            'livereload-start',
            'connect:livereload',
            'open',
            'watch'
        ]);
    });

    grunt.registerTask('test', [
        'clean:server',
        'symlink',
        'coffee',
        'createDefaultTemplate',
        'jst',
        'compass',
        'connect:test',
        'mocha'
    ]);

    grunt.registerTask('build', [
        'clean:dist',
        'symlink',
        'coffee',
        'createDefaultTemplate',
        'jst',
        'compass:dist',
        'useminPrepare',
        'requirejs',
        'imagemin',
        'htmlmin',
        'concat',
        'cssmin',
        'uglify',
        'copy',
        'usemin'
    ]);
    grunt.registerTask('docs', [
        'docco:dist'
    ]);
    grunt.registerTask('default', [
        'saveRevision',
        'jshint',
        'symlink',
        'test',
        'build'
    ]);
    grunt.registerTask('saveRevision', function() {
        grunt.event.once('git-describe', function(rev) {
            grunt.log.writeln('Git Revision: ' + rev);
            grunt.file.write('app/scripts/git.js', '/* jshint -W105 */\n/* global define */\ndefine([], function() { \'use strict\'; return { \'git-commit\': \'' + rev + '\' }; });');
        });
        grunt.task.run('git-describe');
    });
};
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2008-2011  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// NotebookList
//============================================================================

var IPython = (function (IPython) {

    var ClusterList = function (selector) {
        this.selector = selector;
        if (this.selector !== undefined) {
            this.element = $(selector);
            this.style();
            this.bind_events();
        }
    };

    ClusterList.prototype.baseProjectUrl = function(){
        return this._baseProjectUrl || $('body').data('baseProjectUrl');
    };

    ClusterList.prototype.style = function () {
        $('#cluster_toolbar').addClass('list_toolbar');
        $('#cluster_list_info').addClass('toolbar_info');
        $('#cluster_buttons').addClass('toolbar_buttons');
        $('div#cluster_header').addClass('list_header ui-widget ui-widget-header ui-helper-clearfix');
        $('div#cluster_header').children().eq(0).addClass('profile_col');
        $('div#cluster_header').children().eq(1).addClass('action_col');
        $('div#cluster_header').children().eq(2).addClass('engines_col');
        $('div#cluster_header').children().eq(3).addClass('status_col');
        $('#refresh_cluster_list').button({
            icons : {primary: 'ui-icon-arrowrefresh-1-s'},
            text : false
        });
    };

    ClusterList.prototype.bind_events = function () {
        var that = this;
        $('#refresh_cluster_list').click(function () {
            that.load_list();
        });
    };

    ClusterList.prototype.load_list = function () {
        var settings = {
            processData : false,
            cache : false,
            type : "GET",
            dataType : "json",
            success : $.proxy(this.load_list_success, this)
        };
        var url = this.baseProjectUrl() + 'clusters';
        $.ajax(url, settings);
    };

    ClusterList.prototype.clear_list = function () {
        this.element.children('.list_item').remove();
    }

    ClusterList.prototype.load_list_success = function (data, status, xhr) {
        this.clear_list();
        var len = data.length;
        for (var i=0; i<len; i++) {
            var item_div = $('<div/>');
            var item = new ClusterItem(item_div);
            item.update_state(data[i]);
            item_div.data('item', item);
            this.element.append(item_div);
        };
    };

    var ClusterItem = function (element) {
        this.element = $(element);
        this.data = null;
        this.style();
    };

    ClusterItem.prototype.baseProjectUrl = function(){
        return this._baseProjectUrl || $('body').data('baseProjectUrl');
    };

    ClusterItem.prototype.style = function () {
        this.element.addClass('list_item ui-widget ui-widget-content ui-helper-clearfix');
        this.element.css('border-top-style','none');
    }

    ClusterItem.prototype.update_state = function (data) {
        this.data = data;
        if (data.status === 'running') {
            this.state_running();
        } else if (data.status === 'stopped') {
            this.state_stopped();
        };

    }

    ClusterItem.prototype.state_stopped = function () {
        var that = this;
        this.element.empty();
        var profile_col = $('<span/>').addClass('profile_col').text(this.data.profile);
        var status_col = $('<span/>').addClass('status_col').html('stopped');
        var engines_col = $('<span/>').addClass('engines_col');
        var input = $('<input/>').attr('type','number')
                .attr('min',1)
                .attr('value',2)
                .attr('size',3)
                .addClass('engine_num_input');
        engines_col.append(input);
        var action_col = $('<span/>').addClass('action_col');
        var start_button = $('<button>Start</button>').button();
        action_col.append(start_button);
        this.element.append(profile_col).
            append(action_col).
            append(engines_col).
            append(status_col);
        start_button.click(function (e) {
            var n = that.element.find('.engine_num_input').val();
            if (!/^\d+$/.test(n) && n.length>0) {
                status_col.html('invalid engine #');
            } else {
                var settings = {
                    cache : false,
                    data : {n:n},
                    type : "POST",
                    dataType : "json",
                    success : function (data, status, xhr) {
                        that.update_state(data);
                    },
                    error : function (data, status, xhr) {
                        status_col.html("error starting cluster")
                    }
                };
                status_col.html('starting');
                var url = that.baseProjectUrl() + 'clusters/' + that.data.profile + '/start';
                $.ajax(url, settings);
            };
        });
    };

    ClusterItem.prototype.state_running = function () {
        this.element.empty();
        var that = this;
        var profile_col = $('<span/>').addClass('profile_col').text(this.data.profile);
        var status_col = $('<span/>').addClass('status_col').html('running');
        var engines_col = $('<span/>').addClass('engines_col').html(this.data.n);
        var action_col = $('<span/>').addClass('action_col');
        var stop_button = $('<button>Stop</button>').button();
        action_col.append(stop_button);
        this.element.append(profile_col).
            append(action_col).
            append(engines_col).
            append(status_col);
        stop_button.click(function (e) {
            var settings = {
                cache : false,
                type : "POST",
                dataType : "json",
                success : function (data, status, xhr) {
                    that.update_state(data);
                },
                error : function (data, status, xhr) {
                    console.log('error',data);
                    status_col.html("error stopping cluster")
                }
            };
            status_col.html('stopping')
            var url = that.baseProjectUrl() + 'clusters/' + that.data.profile + '/stop';
            $.ajax(url, settings);
        });
    };

    IPython.ClusterList = ClusterList;
    IPython.ClusterItem = ClusterItem;

    return IPython;

}(IPython));

<commit_msg>restore default behavior for automatic cluster size<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2008-2011  The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// NotebookList
//============================================================================

var IPython = (function (IPython) {

    var ClusterList = function (selector) {
        this.selector = selector;
        if (this.selector !== undefined) {
            this.element = $(selector);
            this.style();
            this.bind_events();
        }
    };

    ClusterList.prototype.baseProjectUrl = function(){
        return this._baseProjectUrl || $('body').data('baseProjectUrl');
    };

    ClusterList.prototype.style = function () {
        $('#cluster_toolbar').addClass('list_toolbar');
        $('#cluster_list_info').addClass('toolbar_info');
        $('#cluster_buttons').addClass('toolbar_buttons');
        $('div#cluster_header').addClass('list_header ui-widget ui-widget-header ui-helper-clearfix');
        $('div#cluster_header').children().eq(0).addClass('profile_col');
        $('div#cluster_header').children().eq(1).addClass('action_col');
        $('div#cluster_header').children().eq(2).addClass('engines_col');
        $('div#cluster_header').children().eq(3).addClass('status_col');
        $('#refresh_cluster_list').button({
            icons : {primary: 'ui-icon-arrowrefresh-1-s'},
            text : false
        });
    };

    ClusterList.prototype.bind_events = function () {
        var that = this;
        $('#refresh_cluster_list').click(function () {
            that.load_list();
        });
    };

    ClusterList.prototype.load_list = function () {
        var settings = {
            processData : false,
            cache : false,
            type : "GET",
            dataType : "json",
            success : $.proxy(this.load_list_success, this)
        };
        var url = this.baseProjectUrl() + 'clusters';
        $.ajax(url, settings);
    };

    ClusterList.prototype.clear_list = function () {
        this.element.children('.list_item').remove();
    }

    ClusterList.prototype.load_list_success = function (data, status, xhr) {
        this.clear_list();
        var len = data.length;
        for (var i=0; i<len; i++) {
            var item_div = $('<div/>');
            var item = new ClusterItem(item_div);
            item.update_state(data[i]);
            item_div.data('item', item);
            this.element.append(item_div);
        };
    };

    var ClusterItem = function (element) {
        this.element = $(element);
        this.data = null;
        this.style();
    };

    ClusterItem.prototype.baseProjectUrl = function(){
        return this._baseProjectUrl || $('body').data('baseProjectUrl');
    };

    ClusterItem.prototype.style = function () {
        this.element.addClass('list_item ui-widget ui-widget-content ui-helper-clearfix');
        this.element.css('border-top-style','none');
    }

    ClusterItem.prototype.update_state = function (data) {
        this.data = data;
        if (data.status === 'running') {
            this.state_running();
        } else if (data.status === 'stopped') {
            this.state_stopped();
        };

    }

    ClusterItem.prototype.state_stopped = function () {
        var that = this;
        this.element.empty();
        var profile_col = $('<span/>').addClass('profile_col').text(this.data.profile);
        var status_col = $('<span/>').addClass('status_col').html('stopped');
        var engines_col = $('<span/>').addClass('engines_col');
        var input = $('<input/>').attr('type','number')
                .attr('min',1)
                .attr('size',3)
                .addClass('engine_num_input');
        engines_col.append(input);
        var action_col = $('<span/>').addClass('action_col');
        var start_button = $('<button>Start</button>').button();
        action_col.append(start_button);
        this.element.append(profile_col).
            append(action_col).
            append(engines_col).
            append(status_col);
        start_button.click(function (e) {
            var n = that.element.find('.engine_num_input').val();
            if (!/^\d+$/.test(n) && n.length>0) {
                status_col.html('invalid engine #');
            } else {
                var settings = {
                    cache : false,
                    data : {n:n},
                    type : "POST",
                    dataType : "json",
                    success : function (data, status, xhr) {
                        that.update_state(data);
                    },
                    error : function (data, status, xhr) {
                        status_col.html("error starting cluster")
                    }
                };
                status_col.html('starting');
                var url = that.baseProjectUrl() + 'clusters/' + that.data.profile + '/start';
                $.ajax(url, settings);
            };
        });
    };

    ClusterItem.prototype.state_running = function () {
        this.element.empty();
        var that = this;
        var profile_col = $('<span/>').addClass('profile_col').text(this.data.profile);
        var status_col = $('<span/>').addClass('status_col').html('running');
        var engines_col = $('<span/>').addClass('engines_col').html(this.data.n);
        var action_col = $('<span/>').addClass('action_col');
        var stop_button = $('<button>Stop</button>').button();
        action_col.append(stop_button);
        this.element.append(profile_col).
            append(action_col).
            append(engines_col).
            append(status_col);
        stop_button.click(function (e) {
            var settings = {
                cache : false,
                type : "POST",
                dataType : "json",
                success : function (data, status, xhr) {
                    that.update_state(data);
                },
                error : function (data, status, xhr) {
                    console.log('error',data);
                    status_col.html("error stopping cluster")
                }
            };
            status_col.html('stopping')
            var url = that.baseProjectUrl() + 'clusters/' + that.data.profile + '/stop';
            $.ajax(url, settings);
        });
    };

    IPython.ClusterList = ClusterList;
    IPython.ClusterItem = ClusterItem;

    return IPython;

}(IPython));

<|endoftext|>


<commit_before>angular.module('fitness.game', [])

// directive for auto-focusing popup input when shown
.directive('focusMe', function($timeout) {
  return {
    link: function(scope, element, attrs) {
      $timeout(function() {
        element[0].focus();
      }, 150);
    }
  };
})
.controller('GameCtrl', function($ionicPopup, $ionicModal, $timeout, $interval, gameService, $scope, $state) {

	console.log('Game Controller loaded');

	var self = this;
	var vowels = ['A', 'E', 'I', 'O', 'U'];
	var numVowels;
	var numCons;
	var vowelsRevealed;
	var consRevealed;
	var vowelStack, consStack, thePhrase, noSpace;
	var thePhrase;

	this.init = function(){
		console.log('init game function');
		var obj = {} ;

		if (gameService.activeGame) {
			console.info("new game!")
			self.loadGame();
		}

		else {
			console.info("continue game!")
			obj = gameService.startGame();
			self.guess = "" ;

			gameService.activeGame = obj ;
			gameService.activeGameFlag = true ;

			numVowels = obj.numVowels;
			numCons = obj.numCons;
			vowelsRevealed = 0;
			consRevealed = 0;
			vowelStack = obj.vowelStack;
			consStack = obj.consStack;
			self.phrase = obj.viewModel;
			thePhrase = obj.phrase;
			noSpace = obj.noSpace;
		}

		console.info(thePhrase)
	};

	this.showPopup = function() {
		$scope.data = self.stringifyViewModel();
		var guessPopup = $ionicPopup.show({
			templateUrl: 'pages/game/guess-popup.html',
			title: 'Enter Phrase',
			scope: $scope,
			buttons: [
				{
					text: 'Cancel',
					type: 'button-dark'
				},
				{
					text: 'Solve',
					type: 'button-positive',
					onTap: function(e) {
						if(self.guess.toUpperCase() === thePhrase) {
							guessPopup.close();
							self.goodGuess();
						} else {
							self.badGuess();
						}
					}
				}
			]
		});
	};

	this.stringifyViewModel = function() {
		var str = "";
		console.info(self.phrase)
		for(var a = 0; a < self.phrase.length; a++) {
			for(var b = 0; b < self.phrase[a].length; b++) {
				if(self.phrase[a][b].revealed) {
					str += self.phrase[a][b].letter;
				} else {
					str += "*";
				}
			}
			str += " ";
		}

		return str;
	};

	this.goodGuess = function() {
		console.log("good guess!")
		$ionicPopup.alert({
	     	title: 'You are correct!',
	    	 template: 'Great Job! Play another.'
	   });
		self.revealAll();
		self.initModal("pages/game/win-modal.html");
		$state.go('app.home');
	};

	this.badGuess = function() {
		self.guess = "";
		$ionicPopup.alert({
	     title: 'Wrong Guess!',
	     template: 'Try again!'
	   });
	};

	this.timeExpired = function(){
		self.guess = "";
			$ionicPopup.alert({
	  		   title: 'Time Expired!',
	  		   template: 'Uh no! You ran out of time. Better luck next time!'
	   });

	   $state.go('app.home');

	}

	this.initModal = function(template) {
		$ionicModal.fromTemplateUrl(template, {
			scope: $scope,
			animation: 'slide-in-up'
		}).then(function(modal) {
			self.modal = modal;
			self.modal.show();
		});
	};

	// this will replace the existing reveal function
	this.reveal = function(letterType) {
		var curr;
		if(letterType === "V" && vowelStack.length != 0) {
			curr = vowelStack.shift();
			if (curr) {
				curr.model = curr.letter;
				curr.revealed = true;
				vowelsRevealed++;
			}
		} else if(letterType === "C" && consStack.length != 0) {
			curr = consStack.shift();
			if (curr) {
				curr.model = curr.letter;
				curr.revealed = true;
				consRevealed++;
			}
		} else {
			console.error("something went wrong")
			// either we have a bad lettertype or both stacks are empty
		}
	};

	// reveals the entire phrase
	this.revealAll = function() {
		vowelStack.forEach(function(d) {
			d.model = d.letter;
		});

		consStack.forEach(function(d) {
			d.model = d.letter;
		});
	}

	// takes the number of vowels and consonants that should be revealed and reveals them
	this.catchUp = function(vowels, consonants) {
		if(vowels < 0 || consonants < 0) {
			return;
		}

		for(var a = 0; a < vowels; a++) {
			self.reveal("V");
		}

		for(var b = 0; b < consonants; b++) {
			self.reveal("C");
		}
	};

	this.saveGame = function() {
		console.info("game saved!")
		var state = {
			numVowels: numVowels,
			numCons: numCons,
			vowelsRevealed: vowelsRevealed,
			consRevealed: consRevealed,
			vowelStack: vowelStack,
			consStack: consStack,
			viewModel: self.phrase,
			thePhrase: thePhrase,
			noSpace: noSpace
		};

		return localforage.setItem("gameState", state);
	};

	this.loadGame = function() {
		console.info("game loaded!")
		localforage.getItem("gameState").then(function(savedState) {
			numVowels = savedState.numVowels;
			numCons = savedState.numCons;
			vowelsRevealed = savedState.vowelsRevealed;
			consRevealed = savedState.consRevealed;
			vowelStack = savedState.vowelStack;
			consStack = savedState.consStack;
			self.phrase = savedState.viewModel;
			thePhrase = savedState.thePhrase;
			noSpace = savedState.noSpace;
		});
	};

	this.testReveal = function() {
		if(vowelStack.length > 0) {
			self.reveal("V");
		} else {
			self.reveal("C");
		}
	}

	this.drawFriendly = function() {

		console.log('goal steps ' + self.fitbitData.goals.steps);

		jQuery("#friend-progress").empty();

			self.friendlyProgress = jQuery("#friend-progress").radialMultiProgress("init", {
				'fill': 25,
				'font-size': 14,
				'size': 100,
				'data': [
					{'color': "#2DB1E4", 'range': [0, self.fitbitData.goals.steps]}, // steps
					{'color': "#9CCA13", 'range': [0, self.fitbitData.goals.floors]}, // floors
					{'color': "#cf2583", 'range': [0, 24]} // time
				]
			});

		var dh, dm, ds;
	//	setInterval(function() {
			console.log('in the draw circle func.');

			var date = new Date(),
	        h = date.getHours(),
	        m = date.getMinutes(),
	        s = date.getSeconds();

			self.fitbitData.time = gameService.updateTime(h);

			console.log('hours is ' + h);

	    	self.friendlyProgress.radialMultiProgress("to", {
	      		"index": 0, 'perc': self.fitbitData.steps, 'time': 10
	      	});
	    	self.friendlyProgress.radialMultiProgress("to", {
	    		"index": 1, 'perc': self.fitbitData.floors, 'time': 10
	    	});
	    	self.friendlyProgress.radialMultiProgress("to", {
	    		"index": 2, 'perc': h, 'time': 10
	    	});
	  //  }
//	  }, 1000);
	};

	$scope.$on('$ionicView.leave', function(e) {
		self.saveGame();
	});

	$scope.$on('$ionicView.enter', function(e) {

		self.fitbitData = {} ;
		self.fitbitData.goals = {} ;

		self.fitbitData = gameService.data ;

		console.log('steps in game.js: ' + self.fitbitData.steps);

		console.log('getting access token from storage');
		localforage.getItem('fitbitToken').then(function(token){
			if (!token)
				gameService.reload();

			gameService.fitbitToken = token;
			console.log('saving token to game service: ' + token);
			gameService.getFitbitData();
		});

		self.init();

		$interval.cancel(self.queryInterval);

		self.queryInterval = $interval( function(){ self.refreshData(); } , 260000);

		$timeout( self.drawFriendly, 750);
	});

	this.refreshData = function(){

		gameService.getFitbitData();
		$timeout( self.drawFriendly, 750);
		$scope.$broadcast('scroll.refreshComplete');
		self.computeGameLogic();

	}

	this.computeGameLogic = function(){
		var vowelWorth = parseInt( self.fitbitData.goals.floors /  numVowels);
		var consWorth = parseInt(self.fitbitData.goals.steps /  numCons) ;

		if (consWorth < 100)
			consWorth = 100 ;

		if (vowelWorth < 2)
			vowelWorth = 2 ;

		var vowelCount = parseInt(self.fitbitData.floors / vowelWorth );
		var consCount = parseInt(self.fitbitData.steps / consWorth );
		this.catchUp( vowelCount, consCount );
	}

	this.openGiveUpAlert = function() {
		$ionicPopup.confirm({
	     title: 'Give Up?',
	     template: 'Are you sure you want to give up on this puzzle? You will lose all progress on this puzzle.',
		 okText: 'Give Up'
	   }).then(function(res) {
	   	if(res) {
	   		self.closeGame();
	   	} else {
	   		// do nothing
	   	}
	   });
	};

	this.closeGame = function(){
		// needs a prompt

		gameService.activeGame = false;
		$state.transitionTo('app.home');
	}
});
<commit_msg>changed to dots<commit_after>angular.module('fitness.game', [])

// directive for auto-focusing popup input when shown
.directive('focusMe', function($timeout) {
  return {
    link: function(scope, element, attrs) {
      $timeout(function() {
        element[0].focus();
      }, 150);
    }
  };
})
.controller('GameCtrl', function($ionicPopup, $ionicModal, $timeout, $interval, gameService, $scope, $state) {

	console.log('Game Controller loaded');

	var self = this;
	var vowels = ['A', 'E', 'I', 'O', 'U'];
	var numVowels;
	var numCons;
	var vowelsRevealed;
	var consRevealed;
	var vowelStack, consStack, thePhrase, noSpace;
	var thePhrase;

	this.init = function(){
		console.log('init game function');
		var obj = {} ;

		if (gameService.activeGame) {
			console.info("new game!")
			self.loadGame();
		}

		else {
			console.info("continue game!")
			obj = gameService.startGame();
			self.guess = "" ;

			gameService.activeGame = obj ;
			gameService.activeGameFlag = true ;

			numVowels = obj.numVowels;
			numCons = obj.numCons;
			vowelsRevealed = 0;
			consRevealed = 0;
			vowelStack = obj.vowelStack;
			consStack = obj.consStack;
			self.phrase = obj.viewModel;
			thePhrase = obj.phrase;
			noSpace = obj.noSpace;
		}

		console.info(thePhrase)
	};

	this.showPopup = function() {
		$scope.data = self.stringifyViewModel();
		var guessPopup = $ionicPopup.show({
			templateUrl: 'pages/game/guess-popup.html',
			title: 'Enter Phrase',
			scope: $scope,
			buttons: [
				{
					text: 'Cancel',
					type: 'button-dark'
				},
				{
					text: 'Solve',
					type: 'button-positive',
					onTap: function(e) {
						if(self.guess.toUpperCase() === thePhrase) {
							guessPopup.close();
							self.goodGuess();
						} else {
							self.badGuess();
						}
					}
				}
			]
		});
	};

	this.stringifyViewModel = function() {
		var str = "";
		console.info(self.phrase)
		for(var a = 0; a < self.phrase.length; a++) {
			for(var b = 0; b < self.phrase[a].length; b++) {
				if(self.phrase[a][b].revealed) {
					str += self.phrase[a][b].letter;
				} else {
					str += ".";
				}
			}
			str += " ";
		}

		return str;
	};

	this.goodGuess = function() {
		console.log("good guess!")
		$ionicPopup.alert({
	     	title: 'You are correct!',
	    	 template: 'Great Job! Play another.'
	   });
		self.revealAll();
		self.initModal("pages/game/win-modal.html");
		$state.go('app.home');
	};

	this.badGuess = function() {
		self.guess = "";
		$ionicPopup.alert({
	     title: 'Wrong Guess!',
	     template: 'Try again!'
	   });
	};

	this.timeExpired = function(){
		self.guess = "";
			$ionicPopup.alert({
	  		   title: 'Time Expired!',
	  		   template: 'Uh no! You ran out of time. Better luck next time!'
	   });

	   $state.go('app.home');

	}

	this.initModal = function(template) {
		$ionicModal.fromTemplateUrl(template, {
			scope: $scope,
			animation: 'slide-in-up'
		}).then(function(modal) {
			self.modal = modal;
			self.modal.show();
		});
	};

	// this will replace the existing reveal function
	this.reveal = function(letterType) {
		var curr;
		if(letterType === "V" && vowelStack.length != 0) {
			curr = vowelStack.shift();
			if (curr) {
				curr.model = curr.letter;
				curr.revealed = true;
				vowelsRevealed++;
			}
		} else if(letterType === "C" && consStack.length != 0) {
			curr = consStack.shift();
			if (curr) {
				curr.model = curr.letter;
				curr.revealed = true;
				consRevealed++;
			}
		} else {
			console.error("something went wrong")
			// either we have a bad lettertype or both stacks are empty
		}
	};

	// reveals the entire phrase
	this.revealAll = function() {
		vowelStack.forEach(function(d) {
			d.model = d.letter;
		});

		consStack.forEach(function(d) {
			d.model = d.letter;
		});
	}

	// takes the number of vowels and consonants that should be revealed and reveals them
	this.catchUp = function(vowels, consonants) {
		if(vowels < 0 || consonants < 0) {
			return;
		}

		for(var a = 0; a < vowels; a++) {
			self.reveal("V");
		}

		for(var b = 0; b < consonants; b++) {
			self.reveal("C");
		}
	};

	this.saveGame = function() {
		console.info("game saved!")
		var state = {
			numVowels: numVowels,
			numCons: numCons,
			vowelsRevealed: vowelsRevealed,
			consRevealed: consRevealed,
			vowelStack: vowelStack,
			consStack: consStack,
			viewModel: self.phrase,
			thePhrase: thePhrase,
			noSpace: noSpace
		};

		return localforage.setItem("gameState", state);
	};

	this.loadGame = function() {
		console.info("game loaded!")
		localforage.getItem("gameState").then(function(savedState) {
			numVowels = savedState.numVowels;
			numCons = savedState.numCons;
			vowelsRevealed = savedState.vowelsRevealed;
			consRevealed = savedState.consRevealed;
			vowelStack = savedState.vowelStack;
			consStack = savedState.consStack;
			self.phrase = savedState.viewModel;
			thePhrase = savedState.thePhrase;
			noSpace = savedState.noSpace;
		});
	};

	this.testReveal = function() {
		if(vowelStack.length > 0) {
			self.reveal("V");
		} else {
			self.reveal("C");
		}
	}

	this.drawFriendly = function() {

		console.log('goal steps ' + self.fitbitData.goals.steps);

		jQuery("#friend-progress").empty();

			self.friendlyProgress = jQuery("#friend-progress").radialMultiProgress("init", {
				'fill': 25,
				'font-size': 14,
				'size': 100,
				'data': [
					{'color': "#2DB1E4", 'range': [0, self.fitbitData.goals.steps]}, // steps
					{'color': "#9CCA13", 'range': [0, self.fitbitData.goals.floors]}, // floors
					{'color': "#cf2583", 'range': [0, 24]} // time
				]
			});

		var dh, dm, ds;
	//	setInterval(function() {
			console.log('in the draw circle func.');

			var date = new Date(),
	        h = date.getHours(),
	        m = date.getMinutes(),
	        s = date.getSeconds();

			self.fitbitData.time = gameService.updateTime(h);

			console.log('hours is ' + h);

	    	self.friendlyProgress.radialMultiProgress("to", {
	      		"index": 0, 'perc': self.fitbitData.steps, 'time': 10
	      	});
	    	self.friendlyProgress.radialMultiProgress("to", {
	    		"index": 1, 'perc': self.fitbitData.floors, 'time': 10
	    	});
	    	self.friendlyProgress.radialMultiProgress("to", {
	    		"index": 2, 'perc': h, 'time': 10
	    	});
	  //  }
//	  }, 1000);
	};

	$scope.$on('$ionicView.leave', function(e) {
		self.saveGame();
	});

	$scope.$on('$ionicView.enter', function(e) {

		self.fitbitData = {} ;
		self.fitbitData.goals = {} ;

		self.fitbitData = gameService.data ;

		console.log('steps in game.js: ' + self.fitbitData.steps);

		console.log('getting access token from storage');
		localforage.getItem('fitbitToken').then(function(token){
			if (!token)
				gameService.reload();

			gameService.fitbitToken = token;
			console.log('saving token to game service: ' + token);
			gameService.getFitbitData();
		});

		self.init();

		$interval.cancel(self.queryInterval);

		self.queryInterval = $interval( function(){ self.refreshData(); } , 260000);

		$timeout( self.drawFriendly, 750);
	});

	this.refreshData = function(){

		gameService.getFitbitData();
		$timeout( self.drawFriendly, 750);
		$scope.$broadcast('scroll.refreshComplete');
		self.computeGameLogic();

	}

	this.computeGameLogic = function(){
		var vowelWorth = parseInt( self.fitbitData.goals.floors /  numVowels);
		var consWorth = parseInt(self.fitbitData.goals.steps /  numCons) ;

		if (consWorth < 100)
			consWorth = 100 ;

		if (vowelWorth < 2)
			vowelWorth = 2 ;

		var vowelCount = parseInt(self.fitbitData.floors / vowelWorth );
		var consCount = parseInt(self.fitbitData.steps / consWorth );
		this.catchUp( vowelCount, consCount );
	}

	this.openGiveUpAlert = function() {
		$ionicPopup.confirm({
	     title: 'Give Up?',
	     template: 'Are you sure you want to give up on this puzzle? You will lose all progress on this puzzle.',
		 okText: 'Give Up'
	   }).then(function(res) {
	   	if(res) {
	   		self.closeGame();
	   	} else {
	   		// do nothing
	   	}
	   });
	};

	this.closeGame = function(){
		// needs a prompt

		gameService.activeGame = false;
		$state.transitionTo('app.home');
	}
});
<|endoftext|>