<commit_before>'use strict';
const _ = require('lodash');
const db = require('../schemas');
const Util = require('../modules/Util');

class BurnDownChart {
    static findByProjectId (projectId, {transaction} = {}) {
        return db.BurnDownChart.findAll({where: {projectId}, transaction});
    }

    static calc (projectId, {transaction} = {}) {
        return db.coTransaction({transaction}, function* (transaction) {
            let tasks = yield db.Task.findAll({
                where: {projectId},
                include: [
                    {model: db.Stage, as: 'stage'},
                    {model: db.Cost, as: 'cost'},
                    {model: db.Work, as: 'works', separate: true}
                ],
                transaction
            });
            tasks = tasks.map(x => x.toJSON());

            let logs = yield db.Log.findAll({
                where: {
                    projectId,
                    action: {in: ['archiveTask', 'updateTaskStatus', 'updateTaskStatusAndOrder']}
                },
                transaction
            });
            logs = logs.map(x => x.toJSON());

            const completedTimes = BurnDownChart._calcTaskCompletedTime(logs);

            tasks.forEach(task => {
                const completedTime = completedTimes.find(x => x.taskId === task.id);
                if (completedTime) {
                    task.isCompleted = completedTime.isCompleted;
                    task.completedTime = Number(completedTime.time);
                } else if (_.includes(['done', 'archive'], task.stage.name)) {
                    task.isCompleted = true;
                    task.completedTime = Number(task.createdAt);
                } else {
                    task.isCompleted = false;
                }
            });

            const iterations = yield db.Iteration.findAll({where: {projectId}, transaction});

            const bdc = BurnDownChart._calc(tasks, iterations);

            yield db.BurnDownChart.destroy({where: {projectId}, transaction});
            yield db.BurnDownChart.bulkCreate(bdc.map(x => _.assign(x, {projectId})), {transaction});

            return bdc;
        });
    }

    static _calc (tasks, iterations) {
        // イベントを持つユニークな時間
        const times = _.chain(tasks)
            .map('works')
            .flatten()
            .map(x => [x.startTime, x.endTime])
            .flatten()
            .concat(_.map(tasks, 'createdAt'))
            .concat(_.map(tasks, 'completedTime'))
            .concat(_.map(iterations, 'startTime'))
            .concat(_.map(iterations, 'endTime'))
            .push(Number(Date.now()))
            .compact()
            .map(x => Number(x))
            .sortBy()
            .uniq()
            .map(time => ({time, events: []}))
            .value();

        const _times = times.map(x => x.time);

        tasks.forEach(task => {
            _.chain(task.works)
                .map(work => [
                    {name: '0_startWork', time: Number(work.startTime), workId: work.id},
                    {name: '1_endWork', time: Number(work.endTime), workId: work.id}
                ])
                .flatten()
                .concat([{name: '2_createTask', time: Number(task.createdAt), taskId: task.id, cost: task.cost.value}])
                .concat(task.isCompleted ? [{name: '3_completionTask', time: Number(task.completedTime), taskId: task.id, cost: task.cost.value}] : [])
                .forEach(event => {
                    const pos = Util.lowerBound(_times, event.time);
                    times[pos].events.push(event);
                })
                .value();
        });

        iterations.forEach(iteration => {
            [
                {name: '4_startIteration', time: Number(iteration.startTime), iterationId: iteration.id},
                {name: '5_endIteration', time: Number(iteration.endTime), iterationId: iteration.id}
            ].forEach(event => {
                const pos = Util.lowerBound(_times, event.time);
                times[pos].events.push(event);
            });
        });

        let taskNum = 0;
        let completedTaskNum = 0;
        let totalWorkTime = 0;
        let workingWorkIds = [];
        let beforeTime = times.length ? times[0].time : 0;
        const points = times.map(({time, events}) => {
            totalWorkTime += (Number(time) - Number(beforeTime)) * workingWorkIds.length;

            _.chain(events)
                .sortBy('name')
                .forEach(event => {
                    switch (event.name) {
                    case '0_startWork':
                        workingWorkIds.push(event.workId);
                        break;
                    case '1_endWork':
                        _.pull(workingWorkIds, event.workId);
                        break;
                    case '2_createTask':
                        taskNum += event.cost;
                        break;
                    case '3_completionTask':
                        completedTaskNum += event.cost;
                        break;
                    }
                })
                .value();

            beforeTime = time;

            return {taskNum, completedTaskNum, totalWorkTime: Math.floor(totalWorkTime / 1000 / 60)};
        });

        return points;
    }

    static _calcTaskCompletedTime (logs) {
        return _.chain(logs)
            .map(log => {
                log.content = JSON.parse(log.content);
                log.taskId = log.content.task.id;
                return log;
            })
            .groupBy('taskId')
            .map((statusLogs, taskId) => {
                let lastCompletedTime = 0;
                statusLogs.forEach(log => {
                    if (_.includes(['done', 'archive'], log.content.task.stage.name)) {
                        if (!lastCompletedTime) {
                            lastCompletedTime = Number(log.createdAt);
                        }
                    } else {
                        lastCompletedTime = 0;
                    }
                });
                return {taskId: Number(taskId), time: lastCompletedTime, isCompleted: lastCompletedTime > 0};
            })
            .value();
    }
}

module.exports = BurnDownChart;
<commit_msg>fix typo<commit_after>'use strict';
const _ = require('lodash');
const db = require('../schemas');
const Util = require('../modules/util');

class BurnDownChart {
    static findByProjectId (projectId, {transaction} = {}) {
        return db.BurnDownChart.findAll({where: {projectId}, transaction});
    }

    static calc (projectId, {transaction} = {}) {
        return db.coTransaction({transaction}, function* (transaction) {
            let tasks = yield db.Task.findAll({
                where: {projectId},
                include: [
                    {model: db.Stage, as: 'stage'},
                    {model: db.Cost, as: 'cost'},
                    {model: db.Work, as: 'works', separate: true}
                ],
                transaction
            });
            tasks = tasks.map(x => x.toJSON());

            let logs = yield db.Log.findAll({
                where: {
                    projectId,
                    action: {in: ['archiveTask', 'updateTaskStatus', 'updateTaskStatusAndOrder']}
                },
                transaction
            });
            logs = logs.map(x => x.toJSON());

            const completedTimes = BurnDownChart._calcTaskCompletedTime(logs);

            tasks.forEach(task => {
                const completedTime = completedTimes.find(x => x.taskId === task.id);
                if (completedTime) {
                    task.isCompleted = completedTime.isCompleted;
                    task.completedTime = Number(completedTime.time);
                } else if (_.includes(['done', 'archive'], task.stage.name)) {
                    task.isCompleted = true;
                    task.completedTime = Number(task.createdAt);
                } else {
                    task.isCompleted = false;
                }
            });

            const iterations = yield db.Iteration.findAll({where: {projectId}, transaction});

            const bdc = BurnDownChart._calc(tasks, iterations);

            yield db.BurnDownChart.destroy({where: {projectId}, transaction});
            yield db.BurnDownChart.bulkCreate(bdc.map(x => _.assign(x, {projectId})), {transaction});

            return bdc;
        });
    }

    static _calc (tasks, iterations) {
        // イベントを持つユニークな時間
        const times = _.chain(tasks)
            .map('works')
            .flatten()
            .map(x => [x.startTime, x.endTime])
            .flatten()
            .concat(_.map(tasks, 'createdAt'))
            .concat(_.map(tasks, 'completedTime'))
            .concat(_.map(iterations, 'startTime'))
            .concat(_.map(iterations, 'endTime'))
            .push(Number(Date.now()))
            .compact()
            .map(x => Number(x))
            .sortBy()
            .uniq()
            .map(time => ({time, events: []}))
            .value();

        const _times = times.map(x => x.time);

        tasks.forEach(task => {
            _.chain(task.works)
                .map(work => [
                    {name: '0_startWork', time: Number(work.startTime), workId: work.id},
                    {name: '1_endWork', time: Number(work.endTime), workId: work.id}
                ])
                .flatten()
                .concat([{name: '2_createTask', time: Number(task.createdAt), taskId: task.id, cost: task.cost.value}])
                .concat(task.isCompleted ? [{name: '3_completionTask', time: Number(task.completedTime), taskId: task.id, cost: task.cost.value}] : [])
                .forEach(event => {
                    const pos = Util.lowerBound(_times, event.time);
                    times[pos].events.push(event);
                })
                .value();
        });

        iterations.forEach(iteration => {
            [
                {name: '4_startIteration', time: Number(iteration.startTime), iterationId: iteration.id},
                {name: '5_endIteration', time: Number(iteration.endTime), iterationId: iteration.id}
            ].forEach(event => {
                const pos = Util.lowerBound(_times, event.time);
                times[pos].events.push(event);
            });
        });

        let taskNum = 0;
        let completedTaskNum = 0;
        let totalWorkTime = 0;
        let workingWorkIds = [];
        let beforeTime = times.length ? times[0].time : 0;
        const points = times.map(({time, events}) => {
            totalWorkTime += (Number(time) - Number(beforeTime)) * workingWorkIds.length;

            _.chain(events)
                .sortBy('name')
                .forEach(event => {
                    switch (event.name) {
                    case '0_startWork':
                        workingWorkIds.push(event.workId);
                        break;
                    case '1_endWork':
                        _.pull(workingWorkIds, event.workId);
                        break;
                    case '2_createTask':
                        taskNum += event.cost;
                        break;
                    case '3_completionTask':
                        completedTaskNum += event.cost;
                        break;
                    }
                })
                .value();

            beforeTime = time;

            return {taskNum, completedTaskNum, totalWorkTime: Math.floor(totalWorkTime / 1000 / 60)};
        });

        return points;
    }

    static _calcTaskCompletedTime (logs) {
        return _.chain(logs)
            .map(log => {
                log.content = JSON.parse(log.content);
                log.taskId = log.content.task.id;
                return log;
            })
            .groupBy('taskId')
            .map((statusLogs, taskId) => {
                let lastCompletedTime = 0;
                statusLogs.forEach(log => {
                    if (_.includes(['done', 'archive'], log.content.task.stage.name)) {
                        if (!lastCompletedTime) {
                            lastCompletedTime = Number(log.createdAt);
                        }
                    } else {
                        lastCompletedTime = 0;
                    }
                });
                return {taskId: Number(taskId), time: lastCompletedTime, isCompleted: lastCompletedTime > 0};
            })
            .value();
    }
}

module.exports = BurnDownChart;
<|endoftext|>


<commit_before>/**
 * Item View
 *
 * This is the item view, it is rendered when users visit a page of a specific
 * item. This mainly renders the form to edit the item content in.
 */

import React from 'react';
import { Container, Spinner } from 'elemental';
import { connect } from 'react-redux';

import { listsByKey } from '../../../utils/lists';
import CreateForm from '../../shared/CreateForm';
import EditForm from './components/EditForm';
import EditFormHeader from './components/EditFormHeader';
import RelatedItemsList from './components/RelatedItemsList';
import FlashMessages from '../../shared/FlashMessages';

import {
	selectItem,
	loadItemData,
} from './actions';

import {
	selectList,
} from '../List/actions';

var ItemView = React.createClass({
	displayName: 'ItemView',
	contextTypes: {
		router: React.PropTypes.object.isRequired,
	},
	getInitialState () {
		return {
			createIsOpen: false,
		};
	},
	componentDidMount () {
		// When we directly navigate to an item without coming from another client
		// side routed page before, we need to select the list before initializing the item
		this.props.dispatch(selectList(this.props.params.listId));
		this.initializeItem(this.props.params.itemId);
	},
	componentWillReceiveProps (nextProps) {
		// We've opened a new item from the client side routing, so initialize
		// again with the new item id
		if (nextProps.params.itemId !== this.props.params.itemId) {
			this.initializeItem(nextProps.params.itemId);
		}
	},
	// Initialize an item
	initializeItem (itemId) {
		this.props.dispatch(selectItem(itemId));
		this.props.dispatch(loadItemData());
	},
	// Called when a new item is created
	onCreate (item) {
		// Hide the create form
		this.setState({
			createIsOpen: false,
		});
		// Redirect to newly created item path
		const list = this.props.currentList;
		this.context.router.push(`${Keystone.adminPath}/${list.path}/${item.id}`);
	},
	// Open and close the create new item modal
	toggleCreate (visible) {
		this.setState({
			createIsOpen: visible,
		});
	},
	// Render this items relationships
	renderRelationships () {
		const { relationships } = this.props.currentList;
		const keys = Object.keys(relationships);
		if (!keys.length) return;
		return (

				<Container>

Relationships

					{keys.map(key => {
						const relationship = relationships[key];
						const refList = listsByKey[relationship.ref];
						return (
							<RelatedItemsList
								key={relationship.path}
								list={this.props.currentList}
								refList={refList}
								relatedItemId={this.props.params.itemId}
								relationship={relationship}
							/>
						);
					})}
				</Container>

		);
	},
	render () {
		// If we don't have any data yet, show the loading indicator
		if (!this.props.ready) {
			return (

					<Spinner size="md" />

			);
		}
		// When we have the data, render the item view with it
		return (

				{(this.props.error) ? (
					<FlashMessages
						messages={{
							error: [{
								title: "There's a problem with the network, we're trying to reconnect...",
							}],
						}}
					/>
				) : (

						<Container>
							<EditFormHeader
								list={this.props.currentList}
								data={this.props.data}
								toggleCreate={this.toggleCreate}
							/>
							<CreateForm
								list={this.props.currentList}
								isOpen={this.state.createIsOpen}
								onCancel={() => this.toggleCreate(false)}
								onCreate={(item) => this.onCreate(item)}
							/>
							<EditForm
								list={this.props.currentList}
								data={this.props.data}
								dispatch={this.props.dispatch}
								router={this.context.router}
							/>
						</Container>
						{this.renderRelationships()}

				)}

		);
	},
});

module.exports = connect((state) => ({
	data: state.item.data,
	loading: state.item.loading,
	ready: state.item.ready,
	error: state.item.error,
	currentList: state.lists.currentList,
}))(ItemView);
<commit_msg>Set next list upon a list transition within an item.<commit_after>/**
 * Item View
 *
 * This is the item view, it is rendered when users visit a page of a specific
 * item. This mainly renders the form to edit the item content in.
 */

import React from 'react';
import { Container, Spinner } from 'elemental';
import { connect } from 'react-redux';

import { listsByKey } from '../../../utils/lists';
import CreateForm from '../../shared/CreateForm';
import EditForm from './components/EditForm';
import EditFormHeader from './components/EditFormHeader';
import RelatedItemsList from './components/RelatedItemsList';
import FlashMessages from '../../shared/FlashMessages';

import {
	selectItem,
	loadItemData,
} from './actions';

import {
	selectList,
} from '../List/actions';

var ItemView = React.createClass({
	displayName: 'ItemView',
	contextTypes: {
		router: React.PropTypes.object.isRequired,
	},
	getInitialState () {
		return {
			createIsOpen: false,
		};
	},
	componentDidMount () {
		// When we directly navigate to an item without coming from another client
		// side routed page before, we need to select the list before initializing the item
		this.props.dispatch(selectList(this.props.params.listId));
		this.initializeItem(this.props.params.itemId);
	},
	componentWillReceiveProps (nextProps) {
		// We've opened a new item from the client side routing, so initialize
		// again with the new item id
		if (nextProps.params.itemId !== this.props.params.itemId) {
			this.props.dispatch(selectList(nextProps.params.listId));
			this.initializeItem(nextProps.params.itemId);
		}
	},
	// Initialize an item
	initializeItem (itemId) {
		this.props.dispatch(selectItem(itemId));
		this.props.dispatch(loadItemData());
	},
	// Called when a new item is created
	onCreate (item) {
		// Hide the create form
		this.setState({
			createIsOpen: false,
		});
		// Redirect to newly created item path
		const list = this.props.currentList;
		this.context.router.push(`${Keystone.adminPath}/${list.path}/${item.id}`);
	},
	// Open and close the create new item modal
	toggleCreate (visible) {
		this.setState({
			createIsOpen: visible,
		});
	},
	// Render this items relationships
	renderRelationships () {
		const { relationships } = this.props.currentList;
		const keys = Object.keys(relationships);
		if (!keys.length) return;
		return (

				<Container>

Relationships

					{keys.map(key => {
						const relationship = relationships[key];
						const refList = listsByKey[relationship.ref];
						return (
							<RelatedItemsList
								key={relationship.path}
								list={this.props.currentList}
								refList={refList}
								relatedItemId={this.props.params.itemId}
								relationship={relationship}
							/>
						);
					})}
				</Container>

		);
	},
	render () {
		// If we don't have any data yet, show the loading indicator
		if (!this.props.ready) {
			return (

					<Spinner size="md" />

			);
		}
		// When we have the data, render the item view with it
		return (

				{(this.props.error) ? (
					<FlashMessages
						messages={{
							error: [{
								title: "There's a problem with the network, we're trying to reconnect...",
							}],
						}}
					/>
				) : (

						<Container>
							<EditFormHeader
								list={this.props.currentList}
								data={this.props.data}
								toggleCreate={this.toggleCreate}
							/>
							<CreateForm
								list={this.props.currentList}
								isOpen={this.state.createIsOpen}
								onCancel={() => this.toggleCreate(false)}
								onCreate={(item) => this.onCreate(item)}
							/>
							<EditForm
								list={this.props.currentList}
								data={this.props.data}
								dispatch={this.props.dispatch}
								router={this.context.router}
							/>
						</Container>
						{this.renderRelationships()}

				)}

		);
	},
});

module.exports = connect((state) => ({
	data: state.item.data,
	loading: state.item.loading,
	ready: state.item.ready,
	error: state.item.error,
	currentList: state.lists.currentList,
}))(ItemView);
<|endoftext|>


<commit_before>import useSWR from "swr";
import axios from "@agir/lib/utils/axios";

const WP_API_URL = "https://infos.actionpopulaire.fr/wp-json/wp/v2/";
const WP_PAGE_URL = `${WP_API_URL}pages?per_page=100&&_embed=wp:term,wp:featuredmedia`;
const CATEGORY_LIST = [15, 16, 17];

const fetcher = async (url) => {
  const res = await axios.get(url);
  return res.data;
};

/** return [categories, pages] */
export const getWPPagesAndCategories = () => {
  const { data } = useSWR(
    `${WP_PAGE_URL}&categories=${CATEGORY_LIST.toString()}`,
    fetcher,
    {
      revalidateOnFocus: false,
      refreshInterval: 0,
      refreshWhenHidden: false,
    }
  );

  let categories = [];
  const pages = data?.reduce((pagesSorted, page) => {
    const page_categories = page._embedded["wp:term"];
    const filtered_categories = page_categories.reduce((res, cat) => {
      const cat_filtered = cat.filter(
        (c) => c.taxonomy === "category" && CATEGORY_LIST.includes(c.id),
        []
      );
      return [...res, ...cat_filtered];
    }, []);

    // Add to category list
    const category = filtered_categories[0];
    categories[category.id] = { id: category.id, name: category.name };

    const p = {
      id: page.id,
      title: page.title.rendered,
      img: page._embedded["wp:featuredmedia"][0].source_url,
      link: page.link,
      category_id: category.id,
      category_name: category.name,
    };

    if (!pagesSorted[category.id]) pagesSorted[category.id] = [p];
    else pagesSorted[category.id].push(p);

    return pagesSorted;
  }, []);

  return [categories, pages];
};
<commit_msg>refactor: remove useless fetcher declaration<commit_after>import useSWR from "swr";

const WP_API_URL = "https://infos.actionpopulaire.fr/wp-json/wp/v2/";
const WP_PAGE_URL = `${WP_API_URL}pages?per_page=100&&_embed=wp:term,wp:featuredmedia`;
const CATEGORY_LIST = [15, 16, 17];

/** return [categories, pages] */
export const getWPPagesAndCategories = () => {
  const { data } = useSWR(
    `${WP_PAGE_URL}&categories=${CATEGORY_LIST.toString()}`,
    {
      revalidateOnFocus: false,
      refreshInterval: 0,
      refreshWhenHidden: false,
    }
  );

  let categories = [];
  const pages = data?.reduce((pagesSorted, page) => {
    const page_categories = page._embedded["wp:term"];
    const filtered_categories = page_categories.reduce((res, cat) => {
      const cat_filtered = cat.filter(
        (c) => c.taxonomy === "category" && CATEGORY_LIST.includes(c.id),
        []
      );
      return [...res, ...cat_filtered];
    }, []);

    // Add to category list
    const category = filtered_categories[0];
    categories[category.id] = { id: category.id, name: category.name };

    const p = {
      id: page.id,
      title: page.title.rendered,
      img: page._embedded["wp:featuredmedia"][0].source_url,
      link: page.link,
      category_id: category.id,
      category_name: category.name,
    };

    if (!pagesSorted[category.id]) pagesSorted[category.id] = [p];
    else pagesSorted[category.id].push(p);

    return pagesSorted;
  }, []);

  return [categories, pages];
};
<|endoftext|>


<commit_before>const Parser = module.exports.Parser;
const transformMathJS = module.exports.transformMathJS;

const input = document.querySelector('#input');
const output = document.querySelector('#output');
const select = document.querySelector('#asttype');

select.addEventListener('change', () => {
    asttype = select.value;
    update();
})

const params = new URLSearchParams(location.search);

let asttype = 'mast-ast';

if (params.has('math')) {
    input.value = params.get('math');
}
if (params.has('ast')) {
    asttype = params.get('ast');
    select.value = asttype;
}

const parser = new Parser();

const update = () => {
    try {
        let ast = parser.parse(input.value);
        if (asttype === 'mathsteps') {
            ast = transformMathJS(ast);
        }
        output.textContent = JSON.stringify(ast, null, 4);
    } catch (e) {
        output.textContent = e.message;
    }
}

update();

input.addEventListener('input', update);

const permalink = document.querySelector('#permalink');
permalink.addEventListener('click', () => {
    const math = encodeURI(input.value).replace(/\+/g, '%2B');
    window.location = `?math=${math}&ast=${asttype}`;
});
<commit_msg>use 2 space indents for demo<commit_after>const Parser = module.exports.Parser;
const transformMathJS = module.exports.transformMathJS;

const input = document.querySelector('#input');
const output = document.querySelector('#output');
const select = document.querySelector('#asttype');

select.addEventListener('change', () => {
    asttype = select.value;
    update();
})

const params = new URLSearchParams(location.search);

let asttype = 'mast-ast';

if (params.has('math')) {
    input.value = params.get('math');
}
if (params.has('ast')) {
    asttype = params.get('ast');
    select.value = asttype;
}

const parser = new Parser();

const update = () => {
    try {
        let ast = parser.parse(input.value);
        if (asttype === 'mathsteps') {
            ast = transformMathJS(ast);
        }
        output.textContent = JSON.stringify(ast, null, 2);
    } catch (e) {
        output.textContent = e.message;
    }
}

update();

input.addEventListener('input', update);

const permalink = document.querySelector('#permalink');
permalink.addEventListener('click', () => {
    const math = encodeURI(input.value).replace(/\+/g, '%2B');
    window.location = `?math=${math}&ast=${asttype}`;
});
<|endoftext|>


<commit_before>/* sweetScroll load */
document.addEventListener("DOMContentLoaded", function () {
  const sweetScroll = new SweetScroll({/* some options */});

  /* particlesJS.load(@dom-id, @path-json, @callback (optional)); */
  particlesJS('particles-js', {
    "particles": {
      "number": {
        "value": 30,
        "density": {
          "enable": true,
          "value_area": 800
        }
      },
      "color": {
        "value": "#ffffff"
      },
      "shape": {
        "type": "polygon",
        "stroke": {
          "width": 0,
          "color": "#000000"
        },
        "polygon": {
          "nb_sides": 5
        },
        "image": {
          "src": "img/github.svg",
          "width": 100,
          "height": 100
        }
      },
      "opacity": {
        "value": 0.5,
        "random": false,
        "anim": {
          "enable": false,
          "speed": 1,
          "opacity_min": 0.1,
          "sync": false
        }
      },
      "size": {
        "value": 3,
        "random": true,
        "anim": {
          "enable": false,
          "speed": 19.18081918081918,
          "size_min": 0.1,
          "sync": false
        }
      },
      "line_linked": {
        "enable": true,
        "distance": 150,
        "color": "#ffffff",
        "opacity": 0.4,
        "width": 1
      },
      "move": {
        "enable": true,
        "speed": 4,
        "direction": "none",
        "random": true,
        "straight": false,
        "out_mode": "out",
        "bounce": false,
        "attract": {
          "enable": false,
          "rotateX": 600,
          "rotateY": 1200
        }
      },
      nb: 80
    },
    "interactivity": {
      "detect_on": "window",
      "events": {
        "onhover": {
          "enable": false,
          "mode": "grab"
        },
        "onclick": {
          "enable": true,
          "mode": "push"
        },
        "resize": true
      },
      "modes": {
        "grab": {
          "distance": 400,
          "line_linked": {
            "opacity": 1
          }
        },
        "bubble": {
          "distance": 400,
          "size": 40,
          "duration": 2,
          "opacity": 8,
          "speed": 3
        },
        "repulse": {
          "distance": 200,
          "duration": 0.4
        },
        "push": {
          "particles_nb": 4
        },
        "remove": {
          "particles_nb": 2
        }
      }
    },
    "retina_detect": true
  });

}, false);
<commit_msg>Delete app.js<commit_after><|endoftext|>


<commit_before>var lang = {

    default_language: 'en',
    language: 'en',

    strings: {
        en: {
            'score': 'Score',
            'grader_msg': 'Your score is ',
            'validate': 'Validate',
            'placeholder_text': 'Enter text',
            'placeholder_number': 'Enter number',
            'error_number': 'Must be a number',
            'placeholder_string': 'Enter string',
            'error_string': 'Must be a string',
            'placeholder_regexp': 'Enter text',
            'error_regexp': 'Invalid format'
        },
        fr: {}
    },

    set: function(lng) {
        this.language = lng;
    },

    translate: function(key) {
        if(this.strings[this.language] && this.strings[this.language][key]) {
            return this.strings[this.language][key];
        }
        return this.strings[this.default_language][key] || key;
    }

}

var task_token = {

    token: null,

    init: function() {
        var query = document.location.search.replace(/(^\?)/,'').split("&").map(function(n){return n = n.split("="),this[n[0]] = n[1],this}.bind({}))[0];
        this.token = query.sToken || '';
    },

    get: function() {
        return this.token
    },

    update: function(token) {
        this.token = token
    },

    getAnswerToken: function(answer) {
        return null;
    }
}

var task = {}

task.getViews = function(success, error) {
    var views = {
        task: {}
    };
    success(views);
};

task.updateToken = function(token, success, error) {
    task_token.update(token)
    success();
};

task.getHeight = function(success, error) {
    var d = document;
    var h = Math.max(d.body.offsetHeight, d.documentElement.offsetHeight);
    success(h);
};

task.getMetaData = function(success, error) {
    if (typeof json !== 'undefined') {
        success(json);
    } else {
        success({nbHints: 0});
    }
};

task.reloadState = function(state, success, error) { success() }
task.getState = function(success, error) { success("{}")  }
task.reloadStateObject = function(obj) { }
task.getStateObject = function() { return {} }
task.getDefaultStateObject = function() { return {} }

$('solution').hide();
$('#solution').hide();
$('.grader').hide();

// grade

function useGraderData(answer, callback) {
    if(window.QuizzeGrader.grade && window.QuizzeGrader.data) {
        return callback(window.QuizzeGrader.grade(window.QuizzeGrader.data, answer));
    }
    console.error('Local QuizzeGrader not found');
}

function useGraderUrl(url, task_token, answer, callback) {
    var data = {
        action: 'grade',
        task: task_token,
        answer: answer
    }
    $.ajax({
        type: 'POST',
        url: url,
        data: JSON.stringify(data),
        crossDomain: true,
        contentType: 'application/json'
    }).done(function(res) {
        if(res.success) {
            return callback(res.data);
        }
        console.error('Grader response error: ', res);
    }).fail(function(jqxhr, settings, exception ) {
        console.error('Grader url not responding: ' + url);
    });
}

task.load = function(views, success) {
    task_token.init()

    platform.getTaskParams(null, null, function(taskParams) {
        var random = parseInt(taskParams.randomSeed, 10) || 0
        var q = QuizzeUI({
            parent: $('#task'),
            shuffle_questions: random > 0, // in dev mode always 0 here and shuffle disabled
            shuffle_answers: random > 0,
            random: random
        });

        task.showViews = function(views, callback) {
            q.toggleSolutions(!!views.solution);
            $('#solution').toggle(!!views.solution);
            callback()
        }

        task.getAnswer = function(callback) {
            callback(JSON.stringify(q.getAnswer()));
        };

        task.reloadAnswer = function(answer, callback) {
            try {
                answer = JSON.parse(answer);
                q.setAnswer(answer);
            } catch(e) {

            }
            callback();
        };

        function displayScore(score, max_score) {
            var msg = '' + lang.translate('score') + '' + ' ' + score + '/' + max_score + '';
            if($('#score').length == 0) {
                var div = '

';
                $('.taskContent').first().append(div);
            }
            $('#score').html(msg);
        }

        task.gradeAnswer = function(answer, answer_token, callback) {
            answer = JSON.parse(answer);
            function onGrade(result) {
                var d = taskParams.maxScore - taskParams.minScore;
                var final_score = Math.max(
                    taskParams.minScore + Math.round(d * result.score),
                    taskParams.noScore || 0
                );
                q.showResult(result.mistakes);
                displayScore(final_score, taskParams.maxScore);
                callback(final_score, lang.translate('grader_msg') + final_score, null);
            }
            var token = task_token.get()
            if(token) {
                useGraderUrl(json.graderUrl, token, answer, onGrade);
            } else {
                useGraderData(answer, onGrade);
            }
        };

        task.reloadAnswerObject = function(answerObj) {
            return q.setAnswer(answerObj);
        }

        task.getAnswerObject = function() {
            return q.getAnswer();
        }

        task.getDefaultAnswerObject = function() {
            return [];
        }

        var btn = $('<button class="btn btn-success btn-validate">' + lang.translate('validate') + '</button>');
        btn.on('click', function() {
            platform.validate('done');
        });
        btn.insertAfter($('.taskContent'));

        success();
    });
};

window.QuizzeGrader = {}

var grader = {
    gradeTask: task.gradeAnswer
};

if(window.platform) {
    platform.initWithTask(task);
}

lang.set(window.stringsLanguage)
<commit_msg>quizze: Fix initWithTask called while document is loading<commit_after>var lang = {

    default_language: 'en',
    language: 'en',

    strings: {
        en: {
            'score': 'Score',
            'grader_msg': 'Your score is ',
            'validate': 'Validate',
            'placeholder_text': 'Enter text',
            'placeholder_number': 'Enter number',
            'error_number': 'Must be a number',
            'placeholder_string': 'Enter string',
            'error_string': 'Must be a string',
            'placeholder_regexp': 'Enter text',
            'error_regexp': 'Invalid format'
        },
        fr: {}
    },

    set: function(lng) {
        this.language = lng;
    },

    translate: function(key) {
        if(this.strings[this.language] && this.strings[this.language][key]) {
            return this.strings[this.language][key];
        }
        return this.strings[this.default_language][key] || key;
    }

}

var task_token = {

    token: null,

    init: function() {
        var query = document.location.search.replace(/(^\?)/,'').split("&").map(function(n){return n = n.split("="),this[n[0]] = n[1],this}.bind({}))[0];
        this.token = query.sToken || '';
    },

    get: function() {
        return this.token
    },

    update: function(token) {
        this.token = token
    },

    getAnswerToken: function(answer) {
        return null;
    }
}

var task = {}

task.getViews = function(success, error) {
    var views = {
        task: {}
    };
    success(views);
};

task.updateToken = function(token, success, error) {
    task_token.update(token)
    success();
};

task.getHeight = function(success, error) {
    var d = document;
    var h = Math.max(d.body.offsetHeight, d.documentElement.offsetHeight);
    success(h);
};

task.getMetaData = function(success, error) {
    if (typeof json !== 'undefined') {
        success(json);
    } else {
        success({nbHints: 0});
    }
};

task.reloadState = function(state, success, error) { success() }
task.getState = function(success, error) { success("{}")  }
task.reloadStateObject = function(obj) { }
task.getStateObject = function() { return {} }
task.getDefaultStateObject = function() { return {} }

$('solution').hide();
$('#solution').hide();
$('.grader').hide();

// grade

function useGraderData(answer, callback) {
    if(window.QuizzeGrader.grade && window.QuizzeGrader.data) {
        return callback(window.QuizzeGrader.grade(window.QuizzeGrader.data, answer));
    }
    console.error('Local QuizzeGrader not found');
}

function useGraderUrl(url, task_token, answer, callback) {
    var data = {
        action: 'grade',
        task: task_token,
        answer: answer
    }
    $.ajax({
        type: 'POST',
        url: url,
        data: JSON.stringify(data),
        crossDomain: true,
        contentType: 'application/json'
    }).done(function(res) {
        if(res.success) {
            return callback(res.data);
        }
        console.error('Grader response error: ', res);
    }).fail(function(jqxhr, settings, exception ) {
        console.error('Grader url not responding: ' + url);
    });
}

task.load = function(views, success) {
    task_token.init()

    platform.getTaskParams(null, null, function(taskParams) {
        var random = parseInt(taskParams.randomSeed, 10) || 0
        var q = QuizzeUI({
            parent: $('#task'),
            shuffle_questions: random > 0, // in dev mode always 0 here and shuffle disabled
            shuffle_answers: random > 0,
            random: random
        });

        task.showViews = function(views, callback) {
            q.toggleSolutions(!!views.solution);
            $('#solution').toggle(!!views.solution);
            callback()
        }

        task.getAnswer = function(callback) {
            callback(JSON.stringify(q.getAnswer()));
        };

        task.reloadAnswer = function(answer, callback) {
            try {
                answer = JSON.parse(answer);
                q.setAnswer(answer);
            } catch(e) {

            }
            callback();
        };

        function displayScore(score, max_score) {
            var msg = '' + lang.translate('score') + '' + ' ' + score + '/' + max_score + '';
            if($('#score').length == 0) {
                var div = '

';
                $('.taskContent').first().append(div);
            }
            $('#score').html(msg);
        }

        task.gradeAnswer = function(answer, answer_token, callback) {
            answer = JSON.parse(answer);
            function onGrade(result) {
                var d = taskParams.maxScore - taskParams.minScore;
                var final_score = Math.max(
                    taskParams.minScore + Math.round(d * result.score),
                    taskParams.noScore || 0
                );
                q.showResult(result.mistakes);
                displayScore(final_score, taskParams.maxScore);
                callback(final_score, lang.translate('grader_msg') + final_score, null);
            }
            var token = task_token.get()
            if(token) {
                useGraderUrl(json.graderUrl, token, answer, onGrade);
            } else {
                useGraderData(answer, onGrade);
            }
        };

        task.reloadAnswerObject = function(answerObj) {
            return q.setAnswer(answerObj);
        }

        task.getAnswerObject = function() {
            return q.getAnswer();
        }

        task.getDefaultAnswerObject = function() {
            return [];
        }

        var btn = $('<button class="btn btn-success btn-validate">' + lang.translate('validate') + '</button>');
        btn.on('click', function() {
            platform.validate('done');
        });
        btn.insertAfter($('.taskContent'));

        success();
    });
};

window.QuizzeGrader = {}

var grader = {
    gradeTask: task.gradeAnswer
};

lang.set(window.stringsLanguage)

$(function() {
    if(window.platform) {
        platform.initWithTask(task);
    }
});
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 app = angular.module('PerfDashApp', ['ngMaterial', 'chart.js']);

var PerfDashApp = function(http, scope) {
    this.http = http;
    this.scope = scope;
    this.metricNames = [];
    this.onClick = this.onClickInternal_.bind(this);
    this.cap = 0;
    this.currentCall = 0;
};

PerfDashApp.prototype.onClickInternal_ = function(data, evt, chart) {
    console.log(this, data, evt, chart);
    if (evt.ctrlKey) {
      this.cap = (chart.scale.min + chart.scale.max) / 2;
      this.labelChanged();
      return;
    }

    // Get location
    // TODO(random-liu): Make the URL configurable if we want to support more
    // buckets in the future.
    window.open("https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/logs/" + this.job + "/" + data[0].label + "/", "_blank");
};

// Fetch data from the server and update the data to display
PerfDashApp.prototype.refresh = function() {
    this.http.get("jobnames")
            .success(function(data) {
                this.jobNames = data;
                //init jobName only if needed
                if (this.jobName == undefined || this.jobNames.indexOf(this.jobName) == -1) {
                    this.jobName = this.jobNames[0];
                }
                this.jobNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.jobNameChanged = function() {
    this.http.get("metriccategorynames", {params: {jobname: this.jobName}})
            .success(function(data) {
                    this.metricCategoryNames = data;
                    if (this.metricCategoryNames == undefined ||  this.metricCategoryNames.indexOf(this.metricCategoryName) == -1) {
                         this.metricCategoryName = this.metricCategoryNames[0]
                    }
                    this.metricCategoryNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.metricCategoryNameChanged = function() {
    this.http.get("metricnames", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName}})
            .success(function(data) {
                    this.metricNames = data;
                    if (this.metricName == undefined ||  this.metricNames.indexOf(this.metricName) == -1) {
                         this.metricName = this.metricNames[0]
                    }
                    this.metricNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected metricName
PerfDashApp.prototype.metricNameChanged = function() {
    var callId = ++this.currentCall;
    this.http.get("buildsdata", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName, metricname: this.metricName}})
            .success(function(data) {
                    if (this.currentCall != callId) {
                            return;
                    }
                    this.data = data.builds;
                    this.job = data.job;
                    this.builds = this.getBuilds();
                    this.labels = this.getLabels();
                    this.labelChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using selected labels
PerfDashApp.prototype.labelChanged = function() {
    this.seriesData = [];
    this.series = [];
    result = this.getData(this.selectedLabels);
    this.options = null;
    var seriesLabels = null;
    var a = 0;
    for (; a < result.length; a++) {
        if ("unit" in result[a] && "data" in result[a] && result[a].data != {}) {
            // All the unit should be the same
            this.options = {scaleLabel: "<%=value%> "+result[a].unit, animation: false};
            // Start with higher percentiles, since their values are usually strictly higher
            // than lower percentiles, which avoids obscuring graph data. It also orders data
            // in the onHover labels more naturally.
            seriesLabels = Object.keys(result[a].data);
            seriesLabels.sort();
            seriesLabels.reverse();
            break;
        }
    }
    if(this.options == null) {
        return;
    }
    angular.forEach(seriesLabels, function(name) {
        this.seriesData.push(this.getStream(result, name));
        this.series.push(name);
    }, this);
    this.cap = 0;
};

// Get all of the builds for the data set (e.g. build numbers)
PerfDashApp.prototype.getBuilds = function() {
    return Object.keys(this.data)
};

// Verify if selected labels are in label set
function verifySelectedLabels(selectedLabels, allLabels) {
    if (selectedLabels == undefined || allLabels == undefined) {
        return false;
    }

    if (Object.keys(selectedLabels).length != Object.keys(allLabels).length) {
        return false;
    }

    var result = true;
    angular.forEach(selectedLabels, function(value, key) {
        if (!(key in allLabels) || !(value in allLabels[key])) {
            result = false;
        }
    });

   return result;
}

// Get the set of all labels (e.g. 'resources', 'verbs') in the data set
PerfDashApp.prototype.getLabels = function() {
    var set = {};
    angular.forEach(this.data, function(items, build) {
        angular.forEach(items, function(item) {
            angular.forEach(item.labels, function(label, name) {
                if (set[name] == undefined) {
                    set[name] = {}
                }
                set[name][label] = true
            });
        });
    });

    if (!verifySelectedLabels(this.selectedLabels, set)) {
        this.selectedLabels = {}
    }
    var labels = {};
    angular.forEach(set, function(items, name) {
        labels[name] = [];
        angular.forEach(items, function(ignore, item) {
            if (this.selectedLabels[name] == undefined) {
              this.selectedLabels[name] = item;
            }
            labels[name].push(item)
        }, this);
    }, this);
    return labels;
};

// Extract a time series of data for specific labels
PerfDashApp.prototype.getData = function(labels) {
    var result = [];
    angular.forEach(this.data, function(items, build) {
        var hasAnyResult = false;
        angular.forEach(items, function(item) {
            var match = true;
            angular.forEach(labels, function(label, name) {
                if (item.labels[name] != label) {
                    match = false;
                }
            });
            if (match) {
                result.push(item);
                hasAnyResult = true;
            }
        });
        if (!hasAnyResult) {
            // We need to add empty object so result series will still correspond to build series
            result.push({});
        }
    });
    return result;
};

// Given a slice of data, turn it into a time series of numbers
// 'data' is an array of APICallLatency objects
// 'stream' is a selector for latency data, (e.g. 'Perc50')
PerfDashApp.prototype.getStream = function(data, stream) {
    var result = [];
    angular.forEach(data, function(value) {
        var x = undefined
        if ("data" in value) {
            x = value.data[stream];
        }
        //This is a handling for undefined values which cause chart.js to not display plots
        //TODO(krzysied): Check whether new version of chart.js has support for this case
        if (x == undefined) {
            x = 0;
        }
        if (this.cap != 0 && x > this.cap) {
            x = this.cap;
        }
        result.push(x);
    }, this);
    return result;
};

app.controller('AppCtrl', ['$scope', '$http', '$interval', function($scope, $http, $interval) {
    $scope.controller = new PerfDashApp($http, $scope);
    $scope.controller.refresh();

    // Refresh every 10 min.  The data only refreshes every 10 minutes on the server
    $interval($scope.controller.refresh.bind($scope.controller), 600000)
}]);
<commit_msg>removing empty labels<commit_after>/*
Copyright 2015 The Kubernetes Authors All rights reserved.

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 app = angular.module('PerfDashApp', ['ngMaterial', 'chart.js']);

var PerfDashApp = function(http, scope) {
    this.http = http;
    this.scope = scope;
    this.metricNames = [];
    this.onClick = this.onClickInternal_.bind(this);
    this.cap = 0;
    this.currentCall = 0;
};

PerfDashApp.prototype.onClickInternal_ = function(data, evt, chart) {
    console.log(this, data, evt, chart);
    if (evt.ctrlKey) {
      this.cap = (chart.scale.min + chart.scale.max) / 2;
      this.labelChanged();
      return;
    }

    // Get location
    // TODO(random-liu): Make the URL configurable if we want to support more
    // buckets in the future.
    window.open("https://k8s-gubernator.appspot.com/build/kubernetes-jenkins/logs/" + this.job + "/" + data[0].label + "/", "_blank");
};

// Fetch data from the server and update the data to display
PerfDashApp.prototype.refresh = function() {
    this.http.get("jobnames")
            .success(function(data) {
                this.jobNames = data;
                //init jobName only if needed
                if (this.jobName == undefined || this.jobNames.indexOf(this.jobName) == -1) {
                    this.jobName = this.jobNames[0];
                }
                this.jobNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.jobNameChanged = function() {
    this.http.get("metriccategorynames", {params: {jobname: this.jobName}})
            .success(function(data) {
                    this.metricCategoryNames = data;
                    if (this.metricCategoryNames == undefined ||  this.metricCategoryNames.indexOf(this.metricCategoryName) == -1) {
                         this.metricCategoryName = this.metricCategoryNames[0]
                    }
                    this.metricCategoryNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected jobName
PerfDashApp.prototype.metricCategoryNameChanged = function() {
    this.http.get("metricnames", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName}})
            .success(function(data) {
                    this.metricNames = data;
                    if (this.metricName == undefined ||  this.metricNames.indexOf(this.metricName) == -1) {
                         this.metricName = this.metricNames[0]
                    }
                    this.metricNameChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using the selected metricName
PerfDashApp.prototype.metricNameChanged = function() {
    var callId = ++this.currentCall;
    this.http.get("buildsdata", {params: {jobname: this.jobName, metriccategoryname: this.metricCategoryName, metricname: this.metricName}})
            .success(function(data) {
                    if (this.currentCall != callId) {
                            return;
                    }
                    this.data = data.builds;
                    this.job = data.job;
                    this.builds = this.getBuilds();
                    this.labels = this.getLabels();
                    this.labelChanged();
            }.bind(this))
    .error(function(data) {
        console.log("error fetching result");
        console.log(data);
    });
};

// Update the data to graph, using selected labels
PerfDashApp.prototype.labelChanged = function() {
    this.seriesData = [];
    this.series = [];
    result = this.getData(this.selectedLabels);
    this.options = null;
    var seriesLabels = null;
    var a = 0;
    for (; a < result.length; a++) {
        if ("unit" in result[a] && "data" in result[a] && result[a].data != {}) {
            // All the unit should be the same
            this.options = {scaleLabel: "<%=value%> "+result[a].unit, animation: false};
            // Start with higher percentiles, since their values are usually strictly higher
            // than lower percentiles, which avoids obscuring graph data. It also orders data
            // in the onHover labels more naturally.
            seriesLabels = Object.keys(result[a].data);
            seriesLabels.sort();
            seriesLabels.reverse();
            break;
        }
    }
    if(this.options == null) {
        return;
    }
    angular.forEach(seriesLabels, function(name) {
        this.seriesData.push(this.getStream(result, name));
        this.series.push(name);
    }, this);
    this.cap = 0;
};

// Get all of the builds for the data set (e.g. build numbers)
PerfDashApp.prototype.getBuilds = function() {
    return Object.keys(this.data)
};

// Verify if selected labels are in label set
function verifySelectedLabels(selectedLabels, allLabels) {
    if (selectedLabels == undefined || allLabels == undefined) {
        return false;
    }

    if (Object.keys(selectedLabels).length != Object.keys(allLabels).length) {
        return false;
    }

    var result = true;
    angular.forEach(selectedLabels, function(value, key) {
        if (!(key in allLabels) || !(value in allLabels[key])) {
            result = false;
        }
    });

   return result;
}

function isEmptySet(obj) {
    var count = 0;
    for (k in obj) {
        if (obj.hasOwnProperty(k)) {
            count++;
        }
    }
    if (count == 0) {
         return true
    }
    if (count == 1) {
         if (obj.hasOwnProperty("")) {
             return true
         }
    }
    return false
}

// Get the set of all labels (e.g. 'resources', 'verbs') in the data set
PerfDashApp.prototype.getLabels = function() {
    var set = {};
    angular.forEach(this.data, function(items, build) {
        angular.forEach(items, function(item) {
            angular.forEach(item.labels, function(label, name) {
                if (set[name] == undefined) {
                    set[name] = {}
                }
                set[name][label] = true
            });
        });
    });

    angular.forEach(set, function(labels, name) {
        if (isEmptySet(labels)) {
            delete set[name]
        }
    });
    if (!verifySelectedLabels(this.selectedLabels, set)) {
        this.selectedLabels = {}
    }
    var labels = {};
    angular.forEach(set, function(items, name) {
        labels[name] = [];
        angular.forEach(items, function(ignore, item) {
            if (this.selectedLabels[name] == undefined) {
              this.selectedLabels[name] = item;
            }
            labels[name].push(item)
        }, this);
    }, this);
    return labels;
};

// Extract a time series of data for specific labels
PerfDashApp.prototype.getData = function(labels) {
    var result = [];
    angular.forEach(this.data, function(items, build) {
        var hasAnyResult = false;
        angular.forEach(items, function(item) {
            var match = true;
            angular.forEach(labels, function(label, name) {
                if (item.labels[name] != label) {
                    match = false;
                }
            });
            if (match) {
                result.push(item);
                hasAnyResult = true;
            }
        });
        if (!hasAnyResult) {
            // We need to add empty object so result series will still correspond to build series
            result.push({});
        }
    });
    return result;
};

// Given a slice of data, turn it into a time series of numbers
// 'data' is an array of APICallLatency objects
// 'stream' is a selector for latency data, (e.g. 'Perc50')
PerfDashApp.prototype.getStream = function(data, stream) {
    var result = [];
    angular.forEach(data, function(value) {
        var x = undefined
        if ("data" in value) {
            x = value.data[stream];
        }
        //This is a handling for undefined values which cause chart.js to not display plots
        //TODO(krzysied): Check whether new version of chart.js has support for this case
        if (x == undefined) {
            x = 0;
        }
        if (this.cap != 0 && x > this.cap) {
            x = this.cap;
        }
        result.push(x);
    }, this);
    return result;
};

app.controller('AppCtrl', ['$scope', '$http', '$interval', function($scope, $http, $interval) {
    $scope.controller = new PerfDashApp($http, $scope);
    $scope.controller.refresh();

    // Refresh every 10 min.  The data only refreshes every 10 minutes on the server
    $interval($scope.controller.refresh.bind($scope.controller), 600000)
}]);
<|endoftext|>


<commit_before>
// The node.js modules used.
var fs = require('fs');
var path = require('path');
var child_process = require('child_process');

var builder = require('xmlbuilder');
var uuid = require('node-uuid');
var readDir = require('readdir');
var ShellJS = require("shelljs");

function WixSDK(output) {

    this._output = output;
}

/**
 * The WiX toolkit works with forward slashes. Convert input paths.
 * @param {String} path Input path
 * @returns {String} Converted output path.
 */
WixSDK.prototype.convertPath =
function(path) {

    return path.replace("\\\\", "/").replace("\\", "/");
};

/**
 * This function generates Windows installer file (.msi) for the given Crosswalk-based application
 *
 * @param {String} app_path Path to the folder containing the application manifest.json file
 * @param {String} xwalk_path Path to the folder containing the Crosswalk build output (e.g. out/Release)
 * @param {Object} meta_data The data used for .msi generation.
 *                           Mandatory fields:
 *                              'app_name' - application name
 *                              'upgrade_id' - package upgrade Id (GUID)
 *                              'manufacturer' - product manufacturer
 *                           Optional fields:
 *                              'icon' - path to the icon to be used for shortcut and in the installed program list
 *                              'product_name' - product name, application name is used by default
 *                              'version' - product version, '0.0.0.0' by default
 *                              'is_64_bit' {Bool} - 64 bit arch. flag, 'false' by default
 *                              'extensions' - path to the Crosswalk C++ extensions to be used by the app
 */
WixSDK.prototype.generateMSI =
function(app_path, xwalk_path, meta_data, callback) {

    var output = this._output;

    if (app_path) {
        app_path = this.convertPath(app_path);
    } else {
        output.error("Path to the application is missing");
        callback(false);
        return;
    }

    if (xwalk_path) {
        xwalk_path = this.convertPath(xwalk_path);
    } else {
        output.error("Path to xwalk binaries is missing");
        callback(false);
        return;
    }

    if (!meta_data) {
        output.error("No meta data object is provided");
        callback(false);
        return;
    }

    // Check the mandatory properties.
    if (!meta_data.hasOwnProperty('app_name')) {
        output.error("Application name must be provided");
        callback(false);
        return;
    }

    if (!meta_data.hasOwnProperty('upgrade_id')) {
        output.error("Package upgrade ID must be provided");
        callback(false);
        return;
    }

    if (!meta_data.hasOwnProperty('manufacturer')) {
        output.error("Manufacturer must be provided");
        callback(false);
        return;
    }

    if (!meta_data.hasOwnProperty('product_name'))
        meta_data.product_name = meta_data.app_name;

    if (!meta_data.hasOwnProperty('version'))
        meta_data.version = '0.0.0.0';

    if (meta_data.hasOwnProperty("icon")) {
        meta_data.icon = this.convertPath(meta_data.icon);
    }

    function HasProductIcon() { return meta_data.hasOwnProperty('icon'); }
    function Is64Bit() { return ('is_64_bit' in meta_data) ? meta_data.is_64_bit : false; }
    function HasExtensions() { return meta_data.hasOwnProperty('extensions'); }

    var root = builder.create('Wix').att('xmlns', 'http://schemas.microsoft.com/wix/2006/wi');

    var product = root.ele('Product', {
        'Id': '*',
        'Name': meta_data.product_name,
        'UpgradeCode': meta_data.upgrade_id,
        'Version': meta_data.version,
        'Manufacturer': meta_data.manufacturer,
        'Language': '1033'
    });

    var package = product.ele('Package', { InstallerVersion: '300', 'Compressed': 'yes' });
    if (Is64Bit())
        package.att('Platform', 'x64');

    product.ele('Media', { Id: '1', 'Cabinet': 'main.cab', 'EmbedCab': 'yes' });

    product.ele('Property', { Id: 'ARPNOREPAIR', 'Value': '1' });
    product.ele('Property', { Id: 'ARPNOMODIFY', 'Value': '1' });

    if (HasProductIcon()) {
        product.ele('Icon', { Id: 'ProductIcon', SourceFile: meta_data.icon });
        product.ele('Property', { Id: 'ARPPRODUCTICON', 'Value': 'ProductIcon' });
    }

    var target_dir = product.ele('Directory', { 'Id': 'TARGETDIR', 'Name': 'SourceDir' });

    var program_files_folder = Is64Bit() ? target_dir.ele('Directory', { Id: 'ProgramFiles64Folder' })
                                         : target_dir.ele('Directory', { Id: 'ProgramFilesFolder' })
    var app_root_folder = program_files_folder.ele('Directory',
                                                   { Id: 'ApplicationRootFolder', 'Name': meta_data.app_name });
    // We're putting web app files to a separate subfolder to avoid name clashes.
    var app_files_folder = app_root_folder.ele('Directory',
                                              { Id: 'ApplicationFilesFolder', 'Name': meta_data.app_name });
    if (HasExtensions()) {
        var app_extensions_folder = app_root_folder.ele('Directory',
                                                       { Id: 'ApplicationExtensionsFolder', 'Name': 'extensions' });
    }

    var program_menu_folder = target_dir.ele('Directory', { Id: 'ProgramMenuFolder' });
    var app_menu_folder = program_menu_folder.ele('Directory',
                                                  { Id: 'ApplicationProgramsFolder', 'Name': meta_data.app_name });

    var file_ids = [];

    function MakeIdFromPath(path) {
        // Only ASCII, digits, '.', '_' are allowed.
        return path.replace(new RegExp('[^A-Za-z0-9_.]', 'g'), '_');
    }
    // To be used for cmd line arguments.
    function InQuotes(arg) {
        return "\"" + arg + "\"";
    }

    function AddFileComponent(node, base_path, relative_path) {
        var file_id = MakeIdFromPath(relative_path);
        file_ids.push(file_id);
        var component = node.ele('Component', { Id: file_id, Guid: uuid.v1() });
        var source_path = (base_path.length == 0) ? relative_path
                                                  : path.join(base_path, relative_path);
        var file = component.ele('File', { Id: file_id, Source: source_path, KeyPath: 'yes' });
        if (Is64Bit()) {
            component.att('Win64', 'yes');
            file.att('ProcessorArchitecture', 'x64');
        }
    }

    AddFileComponent(app_root_folder, xwalk_path, 'xwalk.exe');
    AddFileComponent(app_root_folder, xwalk_path, 'xwalk.pak');
    AddFileComponent(app_root_folder, xwalk_path, 'icudtl.dat');
    AddFileComponent(app_root_folder, xwalk_path, 'ffmpegsumo.dll');
    AddFileComponent(app_root_folder, xwalk_path, 'natives_blob.bin');
    AddFileComponent(app_root_folder, xwalk_path, 'snapshot_blob.bin');

    var subfolder_map = {};

    function GetFolderNode(subfolder, root) {
        if (subfolder in subfolder_map)
            return subfolder_map[subfolder];

        var node;
        var split_index = subfolder.lastIndexOf('/');
        if (split_index == -1) {
            node = root.ele('Directory', { Id: MakeIdFromPath(subfolder), Name: subfolder });
        } else {
            var parent = subfolder.substring(0, split_index);
            var foder_name = subfolder.substring(split_index + 1);
            node = GetFolderNode(parent, root).ele('Directory', { Id: MakeIdFromPath(subfolder), Name: foder_name });
        }

        subfolder_map[subfolder] = node;
        return node;
    }

    var locales_path = path.join(xwalk_path, 'locales');
    if (fs.existsSync(locales_path)) {
        var locales = fs.readdirSync(locales_path);
        locales.forEach(function (locale) {
            AddFileComponent(GetFolderNode('locales', app_root_folder), xwalk_path, path.join(locales_path, locale));
        });
    } else {
        // TODO maybe error or warning
    }

    function installFiles(source_dir_path, dest_folder_object) {
        var app_files = readDir.readSync(source_dir_path);
        app_files.forEach(function (name) {
            var directory = path.dirname(name);
            var node = (directory == '.') ? dest_folder_object : GetFolderNode(directory, dest_folder_object);
            AddFileComponent(node, source_dir_path, name);
        });
    }

    installFiles(app_path, app_files_folder);
    if (HasExtensions())
        installFiles(meta_data.extensions, app_extensions_folder);

    var program_menu_folder_ref = product.ele('DirectoryRef', { Id: 'ApplicationProgramsFolder' });
    var component = program_menu_folder_ref.ele('Component', { Id: 'ApplicationShortcut', Guid: uuid.v1() });
    var cmd_line_args = InQuotes(path.join(meta_data.app_name, 'manifest.json'));
    if (HasExtensions())
        cmd_line_args += ' --external-extensions-path=extensions';
    var shortcut = component.ele('Shortcut', {
        Id: 'ApplicationStartMenuShortcut',
        Name: meta_data.app_name,
       // Description: 'blah blah',
        Target: '[#xwalk.exe]',
        Arguments: cmd_line_args,
        WorkingDirectory: 'ApplicationRootFolder'
    });
    if (HasProductIcon())
        shortcut.att('Icon', 'ProductIcon');

    component.ele('RemoveFolder', {
        Id: 'ApplicationProgramsFolder',
        On: 'uninstall'
    });
    component.ele('RegistryValue', {
        Root: 'HKCU',
        Key: 'Software\\' + meta_data.manufacturer + '\\' + meta_data.product,
        Name: 'installed',
        Type: 'integer',
        Value: '1',
        KeyPath: 'yes'
    });

    var feature = product.ele('Feature', { Id: 'MainApplication', Level: '1' });
    file_ids.forEach(function (file_id) { feature.ele('ComponentRef', { Id: file_id }); })
    feature.ele('ComponentRef', { Id: "ApplicationShortcut" });

    var xml_str = root.end({ pretty: true });
    var basename = meta_data.product + "-" + meta_data.version;
    fs.writeFileSync(basename + '.wxs', xml_str);
    this.runWix(InQuotes(basename), function(success) {
        if (success) {
            // Pass back built package
            meta_data.msi = basename + ".msi";
            // Only delete on success, for debugging reasons.
            ShellJS.rm("-f", basename + ".wxs");
            ShellJS.rm("-f", basename + ".wixobj");
            ShellJS.rm("-f", basename + ".wixpdb");
        }
        callback(success);
    });
};

WixSDK.prototype.runWix =
function(basename, callback) {

    var candle = "candle -v " + basename + ".wxs";
    this._output.info("Running '" + candle + "'");
    var child = child_process.exec(candle);

    child.stdout.on("data", function(data) {
        this.onData(data);
    }.bind(this));

    child.stderr.on("data", function(data) {
        this._output.warning(data);
    }.bind(this));

    child.on("exit", function(code, signal) {
        if (code) {
            this._output.error("Unhandled error " + code);
            callback(false);
        } else {
            this.runWixLight(basename, callback);
        }
        return;
    }.bind(this));
};

WixSDK.prototype.runWixLight =
function(basename, callback) {

    var light = "light -v " + basename + ".wixobj";
    this._output.info("Running '" + light + "'");
    var child = child_process.exec(light);

    child.stdout.on("data", function(data) {
        this.onData(data);
    }.bind(this));

    child.stderr.on("data", function(data) {
        this._output.warning(data);
    }.bind(this));

    child.on("exit", function(code, signal) {
        if (code) {
            this._output.error("Unhandled error " + code);
        }
        callback(code === 0);
        return;
    });
};

WixSDK.prototype.onData =
function(data) {

};

module.exports = WixSDK;
<commit_msg>WixSDK: Add missing bind() to callback<commit_after>
// The node.js modules used.
var fs = require('fs');
var path = require('path');
var child_process = require('child_process');

var builder = require('xmlbuilder');
var uuid = require('node-uuid');
var readDir = require('readdir');
var ShellJS = require("shelljs");

function WixSDK(output) {

    this._output = output;
}

/**
 * The WiX toolkit works with forward slashes. Convert input paths.
 * @param {String} path Input path
 * @returns {String} Converted output path.
 */
WixSDK.prototype.convertPath =
function(path) {

    return path.replace("\\\\", "/").replace("\\", "/");
};

/**
 * This function generates Windows installer file (.msi) for the given Crosswalk-based application
 *
 * @param {String} app_path Path to the folder containing the application manifest.json file
 * @param {String} xwalk_path Path to the folder containing the Crosswalk build output (e.g. out/Release)
 * @param {Object} meta_data The data used for .msi generation.
 *                           Mandatory fields:
 *                              'app_name' - application name
 *                              'upgrade_id' - package upgrade Id (GUID)
 *                              'manufacturer' - product manufacturer
 *                           Optional fields:
 *                              'icon' - path to the icon to be used for shortcut and in the installed program list
 *                              'product_name' - product name, application name is used by default
 *                              'version' - product version, '0.0.0.0' by default
 *                              'is_64_bit' {Bool} - 64 bit arch. flag, 'false' by default
 *                              'extensions' - path to the Crosswalk C++ extensions to be used by the app
 */
WixSDK.prototype.generateMSI =
function(app_path, xwalk_path, meta_data, callback) {

    var output = this._output;

    if (app_path) {
        app_path = this.convertPath(app_path);
    } else {
        output.error("Path to the application is missing");
        callback(false);
        return;
    }

    if (xwalk_path) {
        xwalk_path = this.convertPath(xwalk_path);
    } else {
        output.error("Path to xwalk binaries is missing");
        callback(false);
        return;
    }

    if (!meta_data) {
        output.error("No meta data object is provided");
        callback(false);
        return;
    }

    // Check the mandatory properties.
    if (!meta_data.hasOwnProperty('app_name')) {
        output.error("Application name must be provided");
        callback(false);
        return;
    }

    if (!meta_data.hasOwnProperty('upgrade_id')) {
        output.error("Package upgrade ID must be provided");
        callback(false);
        return;
    }

    if (!meta_data.hasOwnProperty('manufacturer')) {
        output.error("Manufacturer must be provided");
        callback(false);
        return;
    }

    if (!meta_data.hasOwnProperty('product_name'))
        meta_data.product_name = meta_data.app_name;

    if (!meta_data.hasOwnProperty('version'))
        meta_data.version = '0.0.0.0';

    if (meta_data.hasOwnProperty("icon")) {
        meta_data.icon = this.convertPath(meta_data.icon);
    }

    function HasProductIcon() { return meta_data.hasOwnProperty('icon'); }
    function Is64Bit() { return ('is_64_bit' in meta_data) ? meta_data.is_64_bit : false; }
    function HasExtensions() { return meta_data.hasOwnProperty('extensions'); }

    var root = builder.create('Wix').att('xmlns', 'http://schemas.microsoft.com/wix/2006/wi');

    var product = root.ele('Product', {
        'Id': '*',
        'Name': meta_data.product_name,
        'UpgradeCode': meta_data.upgrade_id,
        'Version': meta_data.version,
        'Manufacturer': meta_data.manufacturer,
        'Language': '1033'
    });

    var package = product.ele('Package', { InstallerVersion: '300', 'Compressed': 'yes' });
    if (Is64Bit())
        package.att('Platform', 'x64');

    product.ele('Media', { Id: '1', 'Cabinet': 'main.cab', 'EmbedCab': 'yes' });

    product.ele('Property', { Id: 'ARPNOREPAIR', 'Value': '1' });
    product.ele('Property', { Id: 'ARPNOMODIFY', 'Value': '1' });

    if (HasProductIcon()) {
        product.ele('Icon', { Id: 'ProductIcon', SourceFile: meta_data.icon });
        product.ele('Property', { Id: 'ARPPRODUCTICON', 'Value': 'ProductIcon' });
    }

    var target_dir = product.ele('Directory', { 'Id': 'TARGETDIR', 'Name': 'SourceDir' });

    var program_files_folder = Is64Bit() ? target_dir.ele('Directory', { Id: 'ProgramFiles64Folder' })
                                         : target_dir.ele('Directory', { Id: 'ProgramFilesFolder' })
    var app_root_folder = program_files_folder.ele('Directory',
                                                   { Id: 'ApplicationRootFolder', 'Name': meta_data.app_name });
    // We're putting web app files to a separate subfolder to avoid name clashes.
    var app_files_folder = app_root_folder.ele('Directory',
                                              { Id: 'ApplicationFilesFolder', 'Name': meta_data.app_name });
    if (HasExtensions()) {
        var app_extensions_folder = app_root_folder.ele('Directory',
                                                       { Id: 'ApplicationExtensionsFolder', 'Name': 'extensions' });
    }

    var program_menu_folder = target_dir.ele('Directory', { Id: 'ProgramMenuFolder' });
    var app_menu_folder = program_menu_folder.ele('Directory',
                                                  { Id: 'ApplicationProgramsFolder', 'Name': meta_data.app_name });

    var file_ids = [];

    function MakeIdFromPath(path) {
        // Only ASCII, digits, '.', '_' are allowed.
        return path.replace(new RegExp('[^A-Za-z0-9_.]', 'g'), '_');
    }
    // To be used for cmd line arguments.
    function InQuotes(arg) {
        return "\"" + arg + "\"";
    }

    function AddFileComponent(node, base_path, relative_path) {
        var file_id = MakeIdFromPath(relative_path);
        file_ids.push(file_id);
        var component = node.ele('Component', { Id: file_id, Guid: uuid.v1() });
        var source_path = (base_path.length == 0) ? relative_path
                                                  : path.join(base_path, relative_path);
        var file = component.ele('File', { Id: file_id, Source: source_path, KeyPath: 'yes' });
        if (Is64Bit()) {
            component.att('Win64', 'yes');
            file.att('ProcessorArchitecture', 'x64');
        }
    }

    AddFileComponent(app_root_folder, xwalk_path, 'xwalk.exe');
    AddFileComponent(app_root_folder, xwalk_path, 'xwalk.pak');
    AddFileComponent(app_root_folder, xwalk_path, 'icudtl.dat');
    AddFileComponent(app_root_folder, xwalk_path, 'ffmpegsumo.dll');
    AddFileComponent(app_root_folder, xwalk_path, 'natives_blob.bin');
    AddFileComponent(app_root_folder, xwalk_path, 'snapshot_blob.bin');

    var subfolder_map = {};

    function GetFolderNode(subfolder, root) {
        if (subfolder in subfolder_map)
            return subfolder_map[subfolder];

        var node;
        var split_index = subfolder.lastIndexOf('/');
        if (split_index == -1) {
            node = root.ele('Directory', { Id: MakeIdFromPath(subfolder), Name: subfolder });
        } else {
            var parent = subfolder.substring(0, split_index);
            var foder_name = subfolder.substring(split_index + 1);
            node = GetFolderNode(parent, root).ele('Directory', { Id: MakeIdFromPath(subfolder), Name: foder_name });
        }

        subfolder_map[subfolder] = node;
        return node;
    }

    var locales_path = path.join(xwalk_path, 'locales');
    if (fs.existsSync(locales_path)) {
        var locales = fs.readdirSync(locales_path);
        locales.forEach(function (locale) {
            AddFileComponent(GetFolderNode('locales', app_root_folder), xwalk_path, path.join(locales_path, locale));
        });
    } else {
        // TODO maybe error or warning
    }

    function installFiles(source_dir_path, dest_folder_object) {
        var app_files = readDir.readSync(source_dir_path);
        app_files.forEach(function (name) {
            var directory = path.dirname(name);
            var node = (directory == '.') ? dest_folder_object : GetFolderNode(directory, dest_folder_object);
            AddFileComponent(node, source_dir_path, name);
        });
    }

    installFiles(app_path, app_files_folder);
    if (HasExtensions())
        installFiles(meta_data.extensions, app_extensions_folder);

    var program_menu_folder_ref = product.ele('DirectoryRef', { Id: 'ApplicationProgramsFolder' });
    var component = program_menu_folder_ref.ele('Component', { Id: 'ApplicationShortcut', Guid: uuid.v1() });
    var cmd_line_args = InQuotes(path.join(meta_data.app_name, 'manifest.json'));
    if (HasExtensions())
        cmd_line_args += ' --external-extensions-path=extensions';
    var shortcut = component.ele('Shortcut', {
        Id: 'ApplicationStartMenuShortcut',
        Name: meta_data.app_name,
       // Description: 'blah blah',
        Target: '[#xwalk.exe]',
        Arguments: cmd_line_args,
        WorkingDirectory: 'ApplicationRootFolder'
    });
    if (HasProductIcon())
        shortcut.att('Icon', 'ProductIcon');

    component.ele('RemoveFolder', {
        Id: 'ApplicationProgramsFolder',
        On: 'uninstall'
    });
    component.ele('RegistryValue', {
        Root: 'HKCU',
        Key: 'Software\\' + meta_data.manufacturer + '\\' + meta_data.product,
        Name: 'installed',
        Type: 'integer',
        Value: '1',
        KeyPath: 'yes'
    });

    var feature = product.ele('Feature', { Id: 'MainApplication', Level: '1' });
    file_ids.forEach(function (file_id) { feature.ele('ComponentRef', { Id: file_id }); })
    feature.ele('ComponentRef', { Id: "ApplicationShortcut" });

    var xml_str = root.end({ pretty: true });
    var basename = meta_data.product + "-" + meta_data.version;
    fs.writeFileSync(basename + '.wxs', xml_str);
    this.runWix(InQuotes(basename), function(success) {
        if (success) {
            // Pass back built package
            meta_data.msi = basename + ".msi";
            // Only delete on success, for debugging reasons.
            ShellJS.rm("-f", basename + ".wxs");
            ShellJS.rm("-f", basename + ".wixobj");
            ShellJS.rm("-f", basename + ".wixpdb");
        }
        callback(success);
    });
};

WixSDK.prototype.runWix =
function(basename, callback) {

    var candle = "candle -v " + basename + ".wxs";
    this._output.info("Running '" + candle + "'");
    var child = child_process.exec(candle);

    child.stdout.on("data", function(data) {
        this.onData(data);
    }.bind(this));

    child.stderr.on("data", function(data) {
        this._output.warning(data);
    }.bind(this));

    child.on("exit", function(code, signal) {
        if (code) {
            this._output.error("Unhandled error " + code);
            callback(false);
        } else {
            this.runWixLight(basename, callback);
        }
        return;
    }.bind(this));
};

WixSDK.prototype.runWixLight =
function(basename, callback) {

    var light = "light -v " + basename + ".wixobj";
    this._output.info("Running '" + light + "'");
    var child = child_process.exec(light);

    child.stdout.on("data", function(data) {
        this.onData(data);
    }.bind(this));

    child.stderr.on("data", function(data) {
        this._output.warning(data);
    }.bind(this));

    child.on("exit", function(code, signal) {
        if (code) {
            this._output.error("Unhandled error " + code);
        }
        callback(code === 0);
        return;
    }.bind(this));
};

WixSDK.prototype.onData =
function(data) {

};

module.exports = WixSDK;
<|endoftext|>


<commit_before>'use strict';

function draw_logic(){
    for(var vertex in vertices){
        canvas_draw_path(
          [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertex]['dy'],
            },
            {
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
          {},
          'stroke'
        );
        canvas_draw_path(
          [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'x': vertices[vertices[vertex]['parent']]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
          {},
          'stroke'
        );
    }

    // Draw vertices_amount and lineWidth.
    canvas_buffer.fillText(
      vertices_amount,
      0,
      25
    );
    canvas_buffer.fillText(
      canvas_buffer.lineWidth,
      0,
      50
    );
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] += vertices[vertex]['speed'];
        if(vertices[vertex]['loop'] > 359){
            vertices[vertex]['loop'] -= 360;

        }else if(vertices[vertex]['loop'] < 0){
            vertices[vertex]['loop'] += 360;
        }

        var rotation = vertices[vertex]['loop'] * math_degree;

        vertices[vertex]['dx'] =
          canvas_x
          + vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(rotation);
        vertices[vertex]['dy'] =
          canvas_y
          + vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(rotation);
    }
}

function randomize(){
    vertices.length = 0;

    var loop_counter = vertices_amount - 1;
    do{
        vertices.push({
          'dx': 0,
          'dy': 0,
          'loop': random_integer(50) + 50,
          'parent': vertices_amount - loop_counter,
          'radius': Math.random() * 20 + 5,
          'speed': random_integer(10) - 5 * 2,
          'x': random_integer(500) - 250,
          'y': random_integer(500) - 250,
        });
    }while(loop_counter--);

    vertices[vertices_amount - 1]['parent'] = 0;
}

function resize_logic(){
    canvas_buffer.fillStyle = '#fff';
    canvas_buffer.lineJoin = 'round';
    canvas_buffer.strokeStyle = '#fff';

    randomize();
}

var vertices = [];
var vertices_amount = 23;

window.onload = function(e){
    canvas_init();
    input_init(
      {
        27: {
          'todo': function(){
              canvas_buffer.lineWidth = 1;
              if(vertices_amount !== 23){
                vertices_amount = 23;
                randomize();
              }
          },
        },
        65: {
          'todo': function(){
              canvas_buffer.lineWidth = Math.max(
                canvas_buffer.lineWidth - 1,
                1
              );
          },
        },
        68: {
          'todo': function(){
              canvas_buffer.lineWidth += 1;
          },
        },
        83: {
          'todo': function(){
              vertices_amount = Math.max(
                vertices_amount - 1,
                2
              );
              randomize();
          },
        },
        87: {
          'todo': function(){
              vertices_amount += 1;
              randomize();
          },
        },
      },
      {
        'mousedown': {
          'todo': randomize,
        },
      }
    );
};
<commit_msg>made all other keys randomize<commit_after>'use strict';

function draw_logic(){
    for(var vertex in vertices){
        canvas_draw_path(
          [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertex]['dy'],
            },
            {
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
          {},
          'stroke'
        );
        canvas_draw_path(
          [
            {
              'type': 'moveTo',
              'x': vertices[vertex]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
            {
              'x': vertices[vertices[vertex]['parent']]['dx'],
              'y': vertices[vertices[vertex]['parent']]['dy'],
            },
          ],
          {},
          'stroke'
        );
    }

    // Draw vertices_amount and lineWidth.
    canvas_buffer.fillText(
      vertices_amount,
      0,
      25
    );
    canvas_buffer.fillText(
      canvas_buffer.lineWidth,
      0,
      50
    );
}

function logic(){
    for(var vertex in vertices){
        vertices[vertex]['loop'] += vertices[vertex]['speed'];
        if(vertices[vertex]['loop'] > 359){
            vertices[vertex]['loop'] -= 360;

        }else if(vertices[vertex]['loop'] < 0){
            vertices[vertex]['loop'] += 360;
        }

        var rotation = vertices[vertex]['loop'] * math_degree;

        vertices[vertex]['dx'] =
          canvas_x
          + vertices[vertex]['x']
          + vertices[vertex]['radius']
          * Math.cos(rotation);
        vertices[vertex]['dy'] =
          canvas_y
          + vertices[vertex]['y']
          + vertices[vertex]['radius']
          * Math.sin(rotation);
    }
}

function randomize(){
    vertices.length = 0;

    var loop_counter = vertices_amount - 1;
    do{
        vertices.push({
          'dx': 0,
          'dy': 0,
          'loop': random_integer(50) + 50,
          'parent': vertices_amount - loop_counter,
          'radius': Math.random() * 20 + 5,
          'speed': random_integer(10) - 5 * 2,
          'x': random_integer(500) - 250,
          'y': random_integer(500) - 250,
        });
    }while(loop_counter--);

    vertices[vertices_amount - 1]['parent'] = 0;
}

function resize_logic(){
    canvas_buffer.fillStyle = '#fff';
    canvas_buffer.lineJoin = 'round';
    canvas_buffer.strokeStyle = '#fff';

    randomize();
}

var vertices = [];
var vertices_amount = 23;

window.onload = function(e){
    canvas_init();
    input_init(
      {
        27: {
          'todo': function(){
              canvas_buffer.lineWidth = 1;
              if(vertices_amount !== 23){
                vertices_amount = 23;
                randomize();
              }
          },
        },
        65: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth = Math.max(
                canvas_buffer.lineWidth - 1,
                1
              );
          },
        },
        68: {
          'solo': true,
          'todo': function(){
              canvas_buffer.lineWidth += 1;
          },
        },
        83: {
          'todo': function(){
              vertices_amount = Math.max(
                vertices_amount - 1,
                2
              );
              randomize();
          },
        },
        87: {
          'todo': function(){
              vertices_amount += 1;
              randomize();
          },
        },
        'all': {
          'todo': randomize,
        },
      },
      {
        'mousedown': {
          'todo': randomize,
        },
      }
    );
};
<|endoftext|>