<commit_before>/**
 * @file Menu Base
 * @author qiusiqi(qiusiqi@baidu.com)
 */

import san from 'san';

export default san.defineComponent({
    defaultData() {
        return {
            open: false,
            disabled: false,
            multiple: false,
            autoWidth: true,
            itemClickClose: true,
            useLayerForClickAway: false,
            maxHeight: 500,
            className: 'menu-' + Date.now(),
            anchorOrigin: {
                vertical: 'top',
                horizontal: 'left'
            },
            targetOrigin: {
                vertical: 'top',
                horizontal: 'left'
            },
            zIndex: 101
        };
    },
    filters: {
        yesToBe(value, className) {
            return value ? className : '';
        }
    },
    inited() {
        this.transBoolean('all');
        this.transBoolean('open');
        this.transBoolean('multiple');
        this.transBoolean('disabled');
        this.transBoolean('autoWidth');
        this.transBoolean('itemClickClose');
        this.transBoolean('openImmediately');
        this.transBoolean('useLayerForClickAway');

        this.items = [];
        this.values = [];
        this.name = 'menu';
    },
    created() {
        this.handleClickOff = this.handleClickOff.bind(this);
        this.close = this.close.bind(this);
    },
    messages: {
        'UI:menu-item-selected'(arg) {
            let value = arg.value.value;
            let selectValue = this.data.get('value');

            // 多选
            if (this.data.get('multiple')) {

                let len = selectValue.length;
                let hasSelected = false;

                while (len--) {
                    if (selectValue[len] === value) {
                        selectValue.splice(len, 1);
                        hasSelected = true;
                        break;
                    }
                }

                if (!hasSelected) {
                    selectValue.push(value);
                }
            }
            // 单选
            else {
                selectValue = value;
            }

            this.data.set('value', selectValue);

            // 通过改变为每一个menu item的selectValue值，改变其已选状态
            let len = this.items.length;
            while (len--) {
                this.items[len].data.set('selectValue', selectValue);
            }

            // 触发owner的onChange
            this.fire('change', this.sortValues());
            // 收起menu
            this.toggleMenu(arg.value.evt, true, 'ITEM');
        },
        'UI:menu-item-selected-text'(arg) {
            this.data.set('text', arg.value);
        },
        'UI:menu-item-attached'(arg) {
            this.items.push(arg.target);
            this.values.push(arg.target.data.get('value'));
            // 没有value默认填充第一个item的值
            arg.target.data.set('selectValue', this.data.get('value') || this.items[0].data.get('value'));
        },
        'UI:menu-item-detached'(arg) {
            let len = this.items.length;

            while (len--) {
                if (this.items[len] === arg.target) {
                    this.items.splice(len, 1);
                }
            }
        },
        'UI:menu-panel-attached'(arg) {
            arg.target.parentMenu = this.data.get('className');
        },
        'UI:menu-panel-status-changed'(arg) {
            let value = arg.value;
            this.toggleMenu(null, !value.open, value.driver);
        }
    },
    bindEvent() {
        // 点击menu外位置隐藏menu
        document.addEventListener('click', this.handleClickOff);

        this.watch('all', () => {
            let selectValue = this.data.get('all') ? this.values : [];
            this.data.set('value', selectValue);

            let len = this.items.length;
            while (len--) {
                this.items[len].data.set('selectValue', selectValue);
            }

            this.fire('change', selectValue);
        });
    },
    handleClickOff(e) {
        if (!this.toggleAction) {
            return;
        }
        this.toggleAction--;

        this.toggleMenu(null, true, 'BODY');
    },

    /**
     * menu开关toggle
     *
     * @param {Object} evt event
     * @param {boolean} toClose 是否关闭menu
     * @param {string} driver 开关驱动者
     */
    toggleMenu(evt, toClose, driver) {
        evt && evt.stopPropagation();

        if (this.data.get('disabled')) {
            return;
        }

        let open = !this.data.get('open');
        if (typeof toClose !== 'undefined') {
            open = !toClose;
        }
        if (!open && driver === 'ITEM' && this.data.get('itemClickClose') === false) {
            return;
        }
        else if (open) {
            this.toggleAction = 1;
        }

        this.beforeToggleMenu && this.beforeToggleMenu();

        this.data.set('open', open);
        if (!open) {
            this.fire('close');
        }
        else {
            for (let child of this.owner.childs) {
                if (child.name === 'menu' && child.id !== this.id) {
                    child.close();
                }
            }
        }
    },
    close() {
        this.toggleMenu(null, true);
    },
    sortValues() {
        let value = this.data.get('value');
        if (!this.data.get('multiple')) {
            return value;
        }

        let values = this.values.slice(0);
        let selectValue = value || [];
        let len = values.length;

        while (len--) {
            if (selectValue.indexOf(values[len]) === -1) {
                values.splice(len, 1);
            }
        }

        this.data.set('value', values);
        return values;
    },
    transBoolean(key) {
        let value = this.data.get(key);
        this.data.set(key, value === 'false' ? false : !!value);
    },
    disposed() {
        document.removeEventListener('click', this.handleClickOff);
    }
});
<commit_msg>update menu value changed<commit_after>/**
 * @file Menu Base
 * @author qiusiqi(qiusiqi@baidu.com)
 */

import san from 'san';

export default san.defineComponent({
    defaultData() {
        return {
            open: false,
            disabled: false,
            multiple: false,
            autoWidth: true,
            itemClickClose: true,
            useLayerForClickAway: false,
            maxHeight: 500,
            className: 'menu-' + Date.now(),
            anchorOrigin: {
                vertical: 'top',
                horizontal: 'left'
            },
            targetOrigin: {
                vertical: 'top',
                horizontal: 'left'
            },
            zIndex: 101
        };
    },
    filters: {
        yesToBe(value, className) {
            return value ? className : '';
        }
    },
    inited() {
        this.transBoolean('all');
        this.transBoolean('open');
        this.transBoolean('multiple');
        this.transBoolean('disabled');
        this.transBoolean('autoWidth');
        this.transBoolean('itemClickClose');
        this.transBoolean('openImmediately');
        this.transBoolean('useLayerForClickAway');

        this.items = [];
        this.values = [];
        this.name = 'menu';
    },
    created() {
        this.handleClickOff = this.handleClickOff.bind(this);
        this.close = this.close.bind(this);
    },
    messages: {
        'UI:menu-item-selected'(arg) {
            let value = arg.value.value;
            let selectValue = this.data.get('value');

            // 多选
            if (this.data.get('multiple')) {

                let len = selectValue.length;
                let hasSelected = false;

                while (len--) {
                    if (selectValue[len] === value) {
                        selectValue.splice(len, 1);
                        hasSelected = true;
                        break;
                    }
                }

                if (!hasSelected) {
                    selectValue.push(value);
                }
            }
            // 单选
            else {
                selectValue = value;
            }

            this.data.set('value', selectValue);
            this.broadcast(selectValue);

            // 触发owner的onChange
            this.fire('change', this.sortValues());
            // 收起menu
            this.toggleMenu(arg.value.evt, true, 'ITEM');
        },
        'UI:menu-item-selected-text'(arg) {
            this.data.set('text', arg.value);
        },
        'UI:menu-item-attached'(arg) {
            this.items.push(arg.target);
            this.values.push(arg.target.data.get('value'));
            // 没有value默认填充第一个item的值
            arg.target.data.set('selectValue', this.data.get('value') || this.items[0].data.get('value'));
        },
        'UI:menu-item-detached'(arg) {
            let len = this.items.length;

            while (len--) {
                if (this.items[len] === arg.target) {
                    this.items.splice(len, 1);
                }
            }
        },
        'UI:menu-panel-attached'(arg) {
            arg.target.parentMenu = this.data.get('className');
        },
        'UI:menu-panel-status-changed'(arg) {
            let value = arg.value;
            this.toggleMenu(null, !value.open, value.driver);
        }
    },
    bindEvent() {
        // 点击menu外位置隐藏menu
        document.addEventListener('click', this.handleClickOff);

        this.watch('all', () => {
            let selectValue = this.data.get('all') ? this.values : [];

            this.data.set('value', selectValue);
            this.broadcast(selectValue);
            this.fire('change', selectValue);
        });

        this.watch('value', () => {
            this.broadcast(this.data.get('value'));
        });
    },
    /**
     * 通过改变为每一个menu item的selectValue值，改变其已选状态
     *
     * @param {string} selectValue selectValue
     */
    broadcast(selectValue) {
        let len = this.items.length;
        while (len--) {
            this.items[len].data.set('selectValue', selectValue);
        }
    },
    handleClickOff(e) {
        if (!this.toggleAction) {
            return;
        }
        this.toggleAction--;

        this.toggleMenu(null, true, 'BODY');
    },

    /**
     * menu开关toggle
     *
     * @param {Object} evt event
     * @param {boolean} toClose 是否关闭menu
     * @param {string} driver 开关驱动者
     */
    toggleMenu(evt, toClose, driver) {
        evt && evt.stopPropagation();

        if (this.data.get('disabled')) {
            return;
        }

        let open = !this.data.get('open');
        if (typeof toClose !== 'undefined') {
            open = !toClose;
        }
        if (!open && driver === 'ITEM' && this.data.get('itemClickClose') === false) {
            return;
        }
        else if (open) {
            this.toggleAction = 1;
        }

        this.beforeToggleMenu && this.beforeToggleMenu();

        this.data.set('open', open);
        if (!open) {
            this.fire('close');
        }
        else {
            for (let child of this.owner.childs) {
                if (child.name === 'menu' && child.id !== this.id) {
                    child.close();
                }
            }
        }
    },
    close() {
        this.toggleMenu(null, true);
    },
    sortValues() {
        let value = this.data.get('value');
        if (!this.data.get('multiple')) {
            return value;
        }

        let values = this.values.slice(0);
        let selectValue = value || [];
        let len = values.length;

        while (len--) {
            if (selectValue.indexOf(values[len]) === -1) {
                values.splice(len, 1);
            }
        }

        this.data.set('value', values);
        return values;
    },
    transBoolean(key) {
        let value = this.data.get(key);
        this.data.set(key, value === 'false' ? false : !!value);
    },
    disposed() {
        document.removeEventListener('click', this.handleClickOff);
    }
});
<|endoftext|>


<commit_before>import { change } from "redux-form";

import {
  MOVIES_REQUEST_PENDING,
  MOVIES_REQUEST_SUCCESS,
  MOVIES_REQUEST_FAILURE,
  MOVIE_CREATION_PENDING,
  MOVIE_CREATION_SUCCESS,
  MOVIE_CREATION_FAILURE,
  MOVIE_UPDATE_PENDING,
  MOVIE_UPDATE_SUCCESS,
  MOVIE_UPDATE_FAILURE,
  MOVIE_DELETE_PENDING,
  MOVIE_DELETE_SUCCESS,
  MOVIE_DELETE_FAILURE,
  MOVIE_SEARCH_PENDING,
  MOVIE_SEARCH_SUCCESS,
  MOVIE_SEARCH_FAILURE,
  RESET_PROPOSAL_LIST,
  MOVIE_SYNC,
  PAGINATE_ITEMS,
} from "./ActionTypes";

import { GraphQLClient } from "../Core";
import { queries, mutations } from "./graphql";

import { MOVIE_ITEMS_LIMIT } from "./constants";

const fetch = (offset = 0, limit = MOVIE_ITEMS_LIMIT) => {
  return (dispatch) => {
    dispatch({
      type: MOVIES_REQUEST_PENDING,
    });

    GraphQLClient.query({
      query: queries.MOVIES,
      variables: {
        offset,
        limit,
      },
    })
      .then((response) => {
        const {
          data: { movies },
        } = response;

        dispatch({
          type: MOVIES_REQUEST_SUCCESS,
          payload: {
            movies,
          },
        });
      })
      .catch((error) => {
        dispatch({
          type: MOVIES_REQUEST_FAILURE,
          error,
        });
      });
  };
};

const create = ({ title, direction, releaseDate, poster, formats }) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_CREATION_PENDING,
    });

    return GraphQLClient.mutate({
      mutation: mutations.ADD_MOVIE,
      variables: {
        title,
        direction,
        releaseDate,
        ...(typeof poster === "string"
          ? { posterUrl: poster }
          : { poster: poster[0] }),
        formats: formats.map((format) => format.id),
      },
    })
      .then((response) => {
        const {
          data: { addMovie: movie },
        } = response;
        dispatch({
          type: MOVIE_CREATION_SUCCESS,
          movie,
          flashMessage: `'${movie.title}' has been created successfully.`,
        });

        return movie;
      })
      .catch((error) => {
        dispatch({
          type: MOVIE_CREATION_FAILURE,
          error: error,
          flashMessage: `'${title}' creation fails.`,
        });
      });
  };
};

const update = ({ id, title, direction, releaseDate, poster, formats }) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_UPDATE_PENDING,
    });

    GraphQLClient.mutate({
      mutation: mutations.UPDATE_MOVIE,
      variables: {
        id: parseInt(id),
        title,
        direction,
        releaseDate,
        ...(typeof poster === "string"
          ? { posterUrl: poster }
          : { poster: poster[0] }),
        formats: formats
          .filter((format) => format.id)
          .map((format) => parseInt(format.id)),
      },
    })
      .then((response) => {
        const {
          data: { updateMovie: movie },
        } = response;

        dispatch({
          type: MOVIE_UPDATE_SUCCESS,
          movie,
          flashMessage: `'${title}' has been updated successfully.`,
        });
      })
      .catch((error) => {
        if (
          error.graphQLErrors[0] &&
          error.graphQLErrors[0].extensions &&
          error.graphQLErrors[0].extensions.code &&
          error.graphQLErrors[0].extensions.code === 404
        ) {
          dispatch({
            type: MOVIE_DELETE_SUCCESS,
            id,
            flashMessage: `'${title}' has been previously deleted.`,
          });
        } else {
          dispatch({
            type: MOVIE_UPDATE_FAILURE,
            error,
            flashMessage: `'${title}' update fails.`,
          });
        }
      });
  };
};

const remove = (id, title) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_DELETE_PENDING,
    });

    const successAction = {
      type: MOVIE_DELETE_SUCCESS,
      id: parseInt(id),
      flashMessage: `'${title}' has been deleted successfully.`,
    };

    GraphQLClient.mutate({
      mutation: mutations.DELETE_MOVIE,
      variables: {
        id: parseInt(id),
      },
    })
      .then(() => {
        dispatch(successAction);
      })
      .catch((e) => {
        if (e.graphQLErrors[0]?.extensions?.code === 404) {
          dispatch(successAction);
        } else {
          dispatch({
            type: MOVIE_DELETE_FAILURE,
            error: e,
            flashMessage: `'${title}' deletion fails.`,
          });
        }
      });
  };
};

const search = (terms) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_SEARCH_PENDING,
    });

    GraphQLClient.query({
      query: queries.SEARCH,
      variables: {
        terms,
      },
    })
      .then((response) => {
        const {
          data: { explore: results },
        } = response;

        dispatch({
          type: MOVIE_SEARCH_SUCCESS,
          payload: {
            results,
          },
        });
      })
      .catch((error) => {
        dispatch({
          type: MOVIE_SEARCH_FAILURE,
          error,
        });
      });
  };
};

const resetProposalList = () => {
  return (dispatch) => {
    dispatch({
      type: RESET_PROPOSAL_LIST,
    });
  };
};

const selectProposal = (title, releaseDate, direction, poster) => {
  return (dispatch) => {
    dispatch(change("movie", "title", title));
    dispatch(change("movie", "releaseDate", releaseDate));
    dispatch(change("movie", "direction", direction));
    dispatch(change("movie", "poster", poster));

    dispatch({
      type: RESET_PROPOSAL_LIST,
    });
  };
};

const sync = (movies) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_SYNC,
      payload: {
        movies,
      },
    });
  };
};

const paginate = (offset) => {
  return (dispatch) => {
    dispatch({
      type: PAGINATE_ITEMS,
      payload: {
        offset,
      },
    });
  };
};

export {
  fetch,
  create,
  update,
  remove,
  search,
  resetProposalList,
  selectProposal,
  sync,
  paginate,
};
<commit_msg>code style<commit_after>import { change } from "redux-form";

import {
  MOVIES_REQUEST_PENDING,
  MOVIES_REQUEST_SUCCESS,
  MOVIES_REQUEST_FAILURE,
  MOVIE_CREATION_PENDING,
  MOVIE_CREATION_SUCCESS,
  MOVIE_CREATION_FAILURE,
  MOVIE_UPDATE_PENDING,
  MOVIE_UPDATE_SUCCESS,
  MOVIE_UPDATE_FAILURE,
  MOVIE_DELETE_PENDING,
  MOVIE_DELETE_SUCCESS,
  MOVIE_DELETE_FAILURE,
  MOVIE_SEARCH_PENDING,
  MOVIE_SEARCH_SUCCESS,
  MOVIE_SEARCH_FAILURE,
  RESET_PROPOSAL_LIST,
  MOVIE_SYNC,
  PAGINATE_ITEMS,
} from "./ActionTypes";

import { GraphQLClient } from "../Core";
import { queries, mutations } from "./graphql";

import { MOVIE_ITEMS_LIMIT } from "./constants";

const fetch = (offset = 0, limit = MOVIE_ITEMS_LIMIT) => {
  return (dispatch) => {
    dispatch({
      type: MOVIES_REQUEST_PENDING,
    });

    GraphQLClient.query({
      query: queries.MOVIES,
      variables: {
        offset,
        limit,
      },
    })
      .then((response) => {
        const {
          data: { movies },
        } = response;

        dispatch({
          type: MOVIES_REQUEST_SUCCESS,
          payload: {
            movies,
          },
        });
      })
      .catch((error) => {
        dispatch({
          type: MOVIES_REQUEST_FAILURE,
          error,
        });
      });
  };
};

const create = ({ title, direction, releaseDate, poster, formats }) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_CREATION_PENDING,
    });

    return GraphQLClient.mutate({
      mutation: mutations.ADD_MOVIE,
      variables: {
        title,
        direction,
        releaseDate,
        ...(typeof poster === "string"
          ? { posterUrl: poster }
          : { poster: poster[0] }),
        formats: formats.map((format) => format.id),
      },
    })
      .then((response) => {
        const {
          data: { addMovie: movie },
        } = response;
        dispatch({
          type: MOVIE_CREATION_SUCCESS,
          movie,
          flashMessage: `'${movie.title}' has been created successfully.`,
        });

        return movie;
      })
      .catch((error) => {
        dispatch({
          type: MOVIE_CREATION_FAILURE,
          error: error,
          flashMessage: `'${title}' creation fails.`,
        });
      });
  };
};

const update = ({ id, title, direction, releaseDate, poster, formats }) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_UPDATE_PENDING,
    });

    GraphQLClient.mutate({
      mutation: mutations.UPDATE_MOVIE,
      variables: {
        id: parseInt(id),
        title,
        direction,
        releaseDate,
        ...(typeof poster === "string"
          ? { posterUrl: poster }
          : { poster: poster[0] }),
        formats: formats
          .filter((format) => format.id)
          .map((format) => parseInt(format.id)),
      },
    })
      .then((response) => {
        const {
          data: { updateMovie: movie },
        } = response;

        dispatch({
          type: MOVIE_UPDATE_SUCCESS,
          movie,
          flashMessage: `'${title}' has been updated successfully.`,
        });
      })
      .catch((error) => {
        if (error.graphQLErrors[0]?.extensions?.code === 404) {
          dispatch({
            type: MOVIE_DELETE_SUCCESS,
            id,
            flashMessage: `'${title}' has been previously deleted.`,
          });
        } else {
          dispatch({
            type: MOVIE_UPDATE_FAILURE,
            error,
            flashMessage: `'${title}' update fails.`,
          });
        }
      });
  };
};

const remove = (id, title) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_DELETE_PENDING,
    });

    const successAction = {
      type: MOVIE_DELETE_SUCCESS,
      id: parseInt(id),
      flashMessage: `'${title}' has been deleted successfully.`,
    };

    GraphQLClient.mutate({
      mutation: mutations.DELETE_MOVIE,
      variables: {
        id: parseInt(id),
      },
    })
      .then(() => {
        dispatch(successAction);
      })
      .catch((e) => {
        if (e.graphQLErrors[0]?.extensions?.code === 404) {
          dispatch(successAction);
        } else {
          dispatch({
            type: MOVIE_DELETE_FAILURE,
            error: e,
            flashMessage: `'${title}' deletion fails.`,
          });
        }
      });
  };
};

const search = (terms) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_SEARCH_PENDING,
    });

    GraphQLClient.query({
      query: queries.SEARCH,
      variables: {
        terms,
      },
    })
      .then((response) => {
        const {
          data: { explore: results },
        } = response;

        dispatch({
          type: MOVIE_SEARCH_SUCCESS,
          payload: {
            results,
          },
        });
      })
      .catch((error) => {
        dispatch({
          type: MOVIE_SEARCH_FAILURE,
          error,
        });
      });
  };
};

const resetProposalList = () => {
  return (dispatch) => {
    dispatch({
      type: RESET_PROPOSAL_LIST,
    });
  };
};

const selectProposal = (title, releaseDate, direction, poster) => {
  return (dispatch) => {
    dispatch(change("movie", "title", title));
    dispatch(change("movie", "releaseDate", releaseDate));
    dispatch(change("movie", "direction", direction));
    dispatch(change("movie", "poster", poster));

    dispatch({
      type: RESET_PROPOSAL_LIST,
    });
  };
};

const sync = (movies) => {
  return (dispatch) => {
    dispatch({
      type: MOVIE_SYNC,
      payload: {
        movies,
      },
    });
  };
};

const paginate = (offset) => {
  return (dispatch) => {
    dispatch({
      type: PAGINATE_ITEMS,
      payload: {
        offset,
      },
    });
  };
};

export {
  fetch,
  create,
  update,
  remove,
  search,
  resetProposalList,
  selectProposal,
  sync,
  paginate,
};
<|endoftext|>


<commit_before>import path from 'path';

import sql from 'seriate';
import * as Parameters from './Parameters';

export default class MssqlSnapshot {
	constructor(config) {
		if (!config) throw new Error('No configuration supplied to orchestrate the connection interface.');
		this.config = config;
		this.connected = false;
	}

	connect() {
		return new Promise((resolve, reject) => {
			if (!this.connected)
				sql.addConnection(this.config);
				this.connected = true;
				resolve(`connection added: ${this.config.name}.`);
			reject(`already connected with: ${this.config.name}`);
		});
	}
	connections() {
		return this.connect()
			.then(() => this._connections());
	}

	_connections() {
		return sql.execute(this.config.name, {
			query: sql.fromFile('./queries/connections.sql'),
			params: {
				sourceDbName: Parameters.sourceDbName(this.config.database)
			}
		});
	}

	listAll() {
		return this.connect()
			.then(() => this._listAll())
	}

	_listAll() {
		return sql.execute(this.config.name, {
			query: sql.fromFile('./queries/listSnapshots.sql'),
			params: {
				sourceDbName: Parameters.sourceDbName(this.config.database)
			}
		});
	}

	static _snapshotNameIsValid(snapshotName) {
		if (!snapshotName) throw new Error('No snapshot name supplied.');
		return true;
	}

	getDbMeta(snapshotName, snapshotStoragePath = this.config.snapshotStoragePath) {
		return this.connect()
			.then(() => this._getDbMeta(snapshotName, snapshotStoragePath))
	}

	_getDbMeta(snapshotName, snapshotStoragePath) {
		return sql.execute(this.config, {
			query: sql.fromFile('./queries/getDbMeta.sql'),
			params: {
				query: Parameters.query,
				sourceDbName: Parameters.sourceDbName(this.config.database),
			}
		}).then((result) => ({
			PhysicalName: snapshotStoragePath ? path.join(snapshotStoragePath, snapshotName) : path.join(path.dirname(result[0].PhysicalName), snapshotName),
			LogicalName: result[0].LogicalName,
        }));
	}

	create(snapshotName, snapshotStoragePath = this.config.snapshotStoragePath) {
		MssqlSnapshot._snapshotNameIsValid(snapshotName);
		return this.connect()
			.then(() => this._create(snapshotName, snapshotStoragePath))
	}

	_create(snapshotName, snapshotStoragePath) {
		return this.getDbMeta(snapshotName, snapshotStoragePath)
			.then((dbMeta) => {
				return sql.execute(this.config.name, {
					query: sql.fromFile('./queries/createSnapshot.sql'),
					params: {
						query: Parameters.query,
						sourceDbName: Parameters.sourceDbName(this.config.database),
						snapshotName: Parameters.snapshotName(snapshotName),
						logicalName: Parameters.logicalName(dbMeta.LogicalName),
						snapshotPath: {
							val: dbMeta.PhysicalName,
							type: sql.VARCHARMAX
						}
					}
				});
			});
	}

	delete(snapshotName) {
		MssqlSnapshot._snapshotNameIsValid(snapshotName);
		return this.connect()
			.then(() => this._delete(snapshotName));
	}

	_delete(snapshotName) {
		return sql.execute(this.config.name, {
			query: sql.fromFile('./queries/deleteSnapshot.sql'),
			params: {
				snapshotName: Parameters.snapshotName(snapshotName),
				query: Parameters.query
			}
		});
	}

	restore(snapshotName) {
		MssqlSnapshot._snapshotNameIsValid(snapshotName);
		return this.connect()
			.then(() => this._restore(snapshotName));
	}

	_restore(snapshotName) {
		return sql.getPlainContext(this.config.name)
			.step("bringOffline", {
				query: sql.fromFile('./queries/bringOffline.sql'),
				params: {
					sourceDbName: Parameters.sourceDbName(this.config.database),
					query: Parameters.query,
				}
			})
			.step("bringOnline", {
				query: sql.fromFile('./queries/bringOnline.sql'),
				params: {
					sourceDbName: Parameters.sourceDbName(this.config.database),
					query: Parameters.query,
				}
			})
			.step("restoreSnapshot", (execute, data) => {
				execute({
					query: sql.fromFile('./queries/restoreSnapshot.sql'),
					params: {
						snapshotName: Parameters.snapshotName(snapshotName),
						query: Parameters.query,
						sourceDbName: Parameters.sourceDbName(this.config.database)
					}
				});
			})
			.error((err) => {
				console.log(err);
			});
	}
}
<commit_msg>Promise should not reject if already connected<commit_after>import path from 'path';

import sql from 'seriate';
import * as Parameters from './Parameters';

export default class MssqlSnapshot {
	constructor(config) {
		if (!config) throw new Error('No configuration supplied to orchestrate the connection interface.');
		this.config = config;
		this.connected = false;
	}

	connect() {
		return new Promise((resolve, reject) => {
			if (!this.connected)
				sql.addConnection(this.config);
				this.connected = true;
				resolve(`connection added: ${this.config.name}.`);
			resolve(`already connected with: ${this.config.name}`);
		});
	}
	connections() {
		return this.connect()
			.then(() => this._connections());
	}

	_connections() {
		return sql.execute(this.config.name, {
			query: sql.fromFile('./queries/connections.sql'),
			params: {
				sourceDbName: Parameters.sourceDbName(this.config.database)
			}
		});
	}

	listAll() {
		return this.connect()
			.then(() => this._listAll())
	}

	_listAll() {
		return sql.execute(this.config.name, {
			query: sql.fromFile('./queries/listSnapshots.sql'),
			params: {
				sourceDbName: Parameters.sourceDbName(this.config.database)
			}
		});
	}

	static _snapshotNameIsValid(snapshotName) {
		if (!snapshotName) throw new Error('No snapshot name supplied.');
		return true;
	}

	getDbMeta(snapshotName, snapshotStoragePath = this.config.snapshotStoragePath) {
		return this.connect()
			.then(() => this._getDbMeta(snapshotName, snapshotStoragePath))
	}

	_getDbMeta(snapshotName, snapshotStoragePath) {
		return sql.execute(this.config, {
			query: sql.fromFile('./queries/getDbMeta.sql'),
			params: {
				query: Parameters.query,
				sourceDbName: Parameters.sourceDbName(this.config.database),
			}
		}).then((result) => ({
			PhysicalName: snapshotStoragePath ? path.join(snapshotStoragePath, snapshotName) : path.join(path.dirname(result[0].PhysicalName), snapshotName),
			LogicalName: result[0].LogicalName,
        }));
	}

	create(snapshotName, snapshotStoragePath = this.config.snapshotStoragePath) {
		MssqlSnapshot._snapshotNameIsValid(snapshotName);
		return this.connect()
			.then(() => this._create(snapshotName, snapshotStoragePath))
	}

	_create(snapshotName, snapshotStoragePath) {
		return this.getDbMeta(snapshotName, snapshotStoragePath)
			.then((dbMeta) => {
				return sql.execute(this.config.name, {
					query: sql.fromFile('./queries/createSnapshot.sql'),
					params: {
						query: Parameters.query,
						sourceDbName: Parameters.sourceDbName(this.config.database),
						snapshotName: Parameters.snapshotName(snapshotName),
						logicalName: Parameters.logicalName(dbMeta.LogicalName),
						snapshotPath: {
							val: dbMeta.PhysicalName,
							type: sql.VARCHARMAX
						}
					}
				});
			});
	}

	delete(snapshotName) {
		MssqlSnapshot._snapshotNameIsValid(snapshotName);
		return this.connect()
			.then(() => this._delete(snapshotName));
	}

	_delete(snapshotName) {
		return sql.execute(this.config.name, {
			query: sql.fromFile('./queries/deleteSnapshot.sql'),
			params: {
				snapshotName: Parameters.snapshotName(snapshotName),
				query: Parameters.query
			}
		});
	}

	restore(snapshotName) {
		MssqlSnapshot._snapshotNameIsValid(snapshotName);
		return this.connect()
			.then(() => this._restore(snapshotName));
	}

	_restore(snapshotName) {
		return sql.getPlainContext(this.config.name)
			.step("bringOffline", {
				query: sql.fromFile('./queries/bringOffline.sql'),
				params: {
					sourceDbName: Parameters.sourceDbName(this.config.database),
					query: Parameters.query,
				}
			})
			.step("bringOnline", {
				query: sql.fromFile('./queries/bringOnline.sql'),
				params: {
					sourceDbName: Parameters.sourceDbName(this.config.database),
					query: Parameters.query,
				}
			})
			.step("restoreSnapshot", (execute, data) => {
				execute({
					query: sql.fromFile('./queries/restoreSnapshot.sql'),
					params: {
						snapshotName: Parameters.snapshotName(snapshotName),
						query: Parameters.query,
						sourceDbName: Parameters.sourceDbName(this.config.database)
					}
				});
			})
			.error((err) => {
				console.log(err);
			});
	}
}
<|endoftext|>


<commit_before>(function() {

  function Tuple3(x,y,z) {
		return {
			ctor: "_Tuple3",
			_0: x,
			_1: y,
      _2: z
		};
	}

  Elm.Native.WebRTC = {};

  Elm.Native.WebRTC.make = function(localRuntime) {
    localRuntime.Native = localRuntime.Native || {};
    localRuntime.Native.WebRTC = localRuntime.Native.WebRTC || {};
    if (localRuntime.Native.WebRTC.values) return localRuntime.Native.WebRTC.values;

    var Task = Elm.Native.Task.make(localRuntime);
    var Utils = Elm.Native.Utils.make(localRuntime);
    var NS = Elm.Native.Signal.make(localRuntime);
    var requests = NS.input('WebRTC.requests', Tuple3("", "", ""));
    var _onLocalVideoURL = NS.input('WebRTC.onLocalVideoURL', Utils.Tuple2("", ""));
    var _onRemoteVideoURL = NS.input('WebRTC.onRemoteVideoURL', Utils.Tuple2(Utils.Tuple2("", ""), ""));
    var _onAddConnection = NS.input('WebRTC.onAddConnection',  Utils.Tuple2("", ""));
    var _onRemoveConnection = NS.input('WebRTC.onRemoveConnection',  Utils.Tuple2("", ""));

    //TODO
    var cm = null;
    var clientId = null;
    var room = getRoom();//TODO

    var _initialize = function(_clientId, iceServers) {
      iceServers = listToArray(iceServers);
      clientId = _clientId;
      cm = createConnectionManager({
        iceServers: iceServers
      });
      return Task.asyncFunction(function(callback) {
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var send = function(data) {
      data.room = room;
      data.from = clientId;
      console.log('RTC send: ' + data.type);
      setTimeout(function() {
        localRuntime.notify(requests.id, Tuple3(data.type, data.to || "", data.data));
      });
    };

    var _answerSDP = function(from, data) {
      return Task.asyncFunction(function(callback) {
        answerSDP(clientId, cm, send, {
          from: from,
          data: data
        }, function onRemoteVideoURL(from, mediaType, url) {
          setTimeout(function() {
            localRuntime.notify(_onRemoteVideoURL.id, Utils.Tuple2(Utils.Tuple2(from, mediaType), url));
          });
        }, function onAddConnection(from, mediaType) {
          setTimeout(function() {
            localRuntime.notify(_onAddConnection.id, Utils.Tuple2(from, mediaType));
          });
        }, function onRemoveConnection(from, mediaType) {
          setTimeout(function() {
            localRuntime.notify(_onRemoveConnection.id, Utils.Tuple2(from, mediaType));
          });
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _acceptAnswer = function(from, data) {
      return Task.asyncFunction(function(callback) {
        acceptAnswer(clientId, cm, send, {
          from: from,
          data: data
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _addCandidate = function(from, data) {
      return Task.asyncFunction(function(callback) {
        addCandidate(clientId, cm, send, {
          from: from,
          data: data
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _closeRemoteStream = function(from, data) {
      return Task.asyncFunction(function(callback) {
        console.log(data);
        closeRemoteStream(cm, from, data.mediaType, function onRemoteVideoURL(from, mediaType, url) {
          localRuntime.setTimeout(function(){
            localRuntime.notify(_onRemoteVideoURL.id, Utils.Tuple2(Utils.Tuple2(from, mediaType), url));
          }, 0);
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _startStreaming = function(mediaType, peers) {
      peers = listToArray(peers);
      return Task.asyncFunction(function(callback) {
        offerSDP(clientId, cm, send, mediaType, peers, function onLocalVideoURL(mediaType, url) {
          // console.log([mediaType, url]);
          localRuntime.notify(_onLocalVideoURL.id, Utils.Tuple2(mediaType, url));
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _endStreaming = function(mediaType) {
      return Task.asyncFunction(function(callback) {
        localRuntime.setTimeout(function() {
          localRuntime.notify(_onLocalVideoURL.id, Utils.Tuple2(mediaType, ""));
        }, 0);
        endStreaming(clientId, cm, send, mediaType);
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var beforeJoin = function(peerId) {
      return Task.asyncFunction(function(callback) {
        join(clientId, cm, send, peerId);
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var beforeLeave = function(peerId) {
      return Task.asyncFunction(function(callback) {
        leave(clientId, cm, send, peerId, function onRemoteVideoURL(from, mediaType, url) {
          localRuntime.setTimeout(function() {
            localRuntime.notify(_onRemoteVideoURL.id, Utils.Tuple2(Utils.Tuple2(from, mediaType), url));
          }, 0);
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };

    var currentVolumes = function() {
      var array = cm ? cm.getCurrentVolumes() : [];
      var list = arrayToList(array, function(peerId_volume) {
        return Utils.Tuple2(peerId_volume[0], peerId_volume[1]);
      });
      return list;
    };

    return localRuntime.Native.WebRTC.values = {
      initialize: F2(_initialize),
      answerSDP: F2(_answerSDP),
      acceptAnswer: F2(_acceptAnswer),
      addCandidate: F2(_addCandidate),
      closeRemoteStream: F2(_closeRemoteStream),
      startStreaming: F2(_startStreaming),
      endStreaming: _endStreaming,
      beforeJoin: beforeJoin,
      beforeLeave: beforeLeave,
      requests: requests,
      onLocalVideoURL: _onLocalVideoURL,
      onRemoteVideoURL: _onRemoteVideoURL,
      onAddConnection: _onAddConnection,
      onRemoveConnection: _onRemoveConnection,
      currentVolumes: currentVolumes
    };
  };
  function getRoom() {
    var roomId = decodeURI(location.href.split('/room/')[1].split('?')[0]);
    return roomId;
  }

  function createConnectionManager(connectionOption) {
    var connections = {};//TODO upstream/downstream
    var getConnection = function(id) {
      if(!id) {
        throw new Error('id is null');
      }
      if (!connections[id]) {
        console.log('not exists: ' + id);
        var pc = new RTCPeerConnection(connectionOption);
        connections[id] = pc;
      }
      return connections[id];
    };
    var getAllConnections = function() {
      return Object.keys(connections).map(function(key) {
        return connections[key];
      });
    };
    var removeConnection = function(peerId) {
      delete connections[peerId];
    };
    var removeAllConnections = function(){
      connections = {};
    };

    //----
    var streams = {};
    var audioAnalysers = {};
    var addStream = function(peerId, mediaType, stream) {

      if(window.AudioContext && mediaType === 'mic') {
        setTimeout(function(){
          var context = new AudioContext();
          var source = context.createMediaStreamSource(stream);
          var gainNode = context.createGain();
          gainNode.gain.value = 100.0;

          var analyser = context.createAnalyser();
          // analyser.fftSize = 1024;
          source.connect(gainNode);
          gainNode.connect(analyser);
          // alert(analyser.minDecibels);
          // alert(analyser.maxDecibels);
          // analyser.minDecibel = -40;
          // analyser.maxDecibels = -10;
          // analyser.minDecibels = parseFloat(document.getElementById("min").value);
          // analyser.maxDecibels = parseFloat(document.getElementById("max").value);
          // analyser.smoothingTimeConstant = parseFloat(document.getElementById("smoothing").value);
          audioAnalysers[peerId] = analyser;
        }, 100)

      }
      streams[peerId + mediaType] = stream;
    };
    var getCurrentVolumes = function() {
      var all = Object.keys(audioAnalysers).map(function(peerId) {
        var analyser = audioAnalysers[peerId];
        var data = new Uint8Array(analyser.frequencyBinCount);
        analyser.getByteTimeDomainData(data);
        var sum = 0;
        for(var i = 0; i < data.length; i++) {
          var value = data[i] - 128;
          sum += value > 0 ? value : -value;
        }
        var value = Math.round(sum / data.length);
        return [peerId, value];
      });
      return all;
    };
    var getStream = function(peerId, mediaType) {
      return streams[peerId + mediaType];
    };
    var removeStream = function(peerId, mediaType) {
      delete streams[peerId + mediaType];
    };
    return {
      getConnection: getConnection,
      getAllConnections: getAllConnections,
      removeConnection: removeConnection,
      removeAllConnections: removeAllConnections,
      getStream: getStream,
      addStream: addStream,
      removeStream: removeStream,
      getCurrentVolumes: getCurrentVolumes
    };
  }

  function offerSDP(clientId, cm, send, mediaType, peers, onLocalVideoURL) {
    var mediaOptions = {};
    if(mediaType === 'mic') {
      mediaOptions.audio = true;
      f(mediaOptions);
    } else if(mediaType === 'video') {
      mediaOptions.video = true;
      f(mediaOptions);
    } else if(mediaType === 'screen') {
      getScreenId(function (error, sourceId, mediaOptions) {
        if(error === 'not-installed') {
          alert('Screen Capturing is not installed.');
          return;
        } else if(error === 'installed-disabled') {
          alert('Screen Capturing is installed but disabled.');
          return;
        } else {
          f(mediaOptions);
        }
      });
    }

    function f(mediaOptions) {
      navigator.getUserMedia(mediaOptions, function(stream) {
        console.log(stream);
        console.log(stream.getAudioTracks());
        console.log(stream.getVideoTracks());

        cm.addStream(clientId, mediaType, stream);
        peers.forEach(function(peerId) {
          sendOfferToPeer(clientId, cm, send, peerId, stream, mediaType);
        });
        onLocalVideoURL(mediaType, URL.createObjectURL(stream));

      }, onerror);
    }

  }

  function sendOfferToPeer(clientId, cm, send, peerId, stream, mediaType) {
    if(peerId === clientId) {
      return;
    }
    var pc = cm.getConnection(peerId);
    pc.onicecandidate = function(e) {
      if (e.candidate) {
        setTimeout(function(){
          send({
            type: 'offerCandidate',
            to: peerId,
            data: e.candidate
          });
        }, 2000);
      }
    };

    pc.addStream(stream);

    pc.createOffer(function(offer) {
      // console.log('created offer', offer);

      pc.setLocalDescription(
        new RTCSessionDescription(offer),
        function() { // send offer to server
          send({
            type: 'offerSDP',
            to: peerId,
            data: {
              offer: offer,
              mediaType: mediaType
            }
          });
        }, onerror);
    }, onerror);
  }

  function answerSDP(clientId, cm, send, e, onRemoteVideoURL, onAddConnection, onRemoveConnection) {
    var _from = e.from;
    var pc = cm.getConnection(_from);
    var mediaType = e.data.mediaType;
    pc.onicecandidate = function(e) {
      if (e.candidate) {
        send({
          type: 'answerCandidate',
          to: _from,
          data: e.candidate
        });
      }
    };
    pc.onaddstream = function(e) {
      cm.addStream(_from, mediaType, e.stream);
      onRemoteVideoURL(_from, mediaType, URL.createObjectURL(e.stream));
    };
    pc.onremovestream = function(e) {
      console.log('onremovestream');
      // console.log(e);
      // cm.removeStream(_from, mediaType);
      // onRemoveConnection(_from, mediaType);
    };
    onAddConnection(_from, mediaType);
    pc.setRemoteDescription(
      new RTCSessionDescription(e.data.offer),
      function() {
        pc.createAnswer(function(answer) {
          pc.setLocalDescription(
            new RTCSessionDescription(answer),
            function() {
              send({
                type: 'answerSDP',
                to: e.from,
                data: answer
              });
            }, onerror);
        }, onerror);
      }, onerror);
  }

  function acceptAnswer(clientId, cm, send, e) {
    var pc = cm.getConnection(e.from);
    pc.setRemoteDescription(
      new RTCSessionDescription(e.data),
      function() {
      },
      onerror);
  };

  function addCandidate(clientId, cm, send, e) {
    var pc = cm.getConnection(e.from);
    console.log('addCandidate:', JSON.stringify(e.data));
    if (e.data.candidate) {
      pc.addIceCandidate(new RTCIceCandidate(e.data));
    }
  }

  function endStreaming(clientId, cm, send, mediaType) {
    var stream = cm.getStream(clientId, mediaType);
    console.log(cm.getAllConnections(), mediaType);
    cm.getAllConnections().forEach(function(pc) {
      try {
        console.log(stream);
        pc.removeStream(stream);
      } catch(e) {
        console.error(e);
      }
    });
    cm.removeStream(clientId, mediaType);
    send({
      type: 'endStream',
      to: clientId,
      data: {
        mediaType: mediaType
      }
    });
  }

  // connect curent streams to joined peer
  function join(clientId, cm, send, from) {
    ["mic", "video", "screen"].forEach(function(mediaType) {
      var stream = cm.getStream(clientId, mediaType);
      if(stream) {
        sendOfferToPeer(clientId, cm, send, from, stream, mediaType);
      }
    });
  }
  // unconnect curent streams to joined peer
  function leave(clientId, cm, send, from, onRemoteVideoURL) {
    cm.removeConnection(from);
    ["mic", "video", "screen"].forEach(function(mediaType) {
      closeRemoteStream(cm, from, mediaType, onRemoteVideoURL);
    });
  }

  function closeRemoteStream(cm, remoteClientId, mediaType, onRemoteVideoURL) {
    var pc = cm.getConnection(remoteClientId);
    var stream = cm.getStream(remoteClientId, mediaType);
    if(stream) {
      pc.removeStream(stream);
      cm.removeStream(remoteClientId, mediaType);
    }
    onRemoteVideoURL(remoteClientId, mediaType, "");
  }

  function polyfill() {
    if (!window.RTCPeerConnection) {
      if (window.mozRTCPeerConnection) {
        window.RTCPeerConnection = window.mozRTCPeerConnection;
      } else if (window.webkitRTCPeerConnection) {
        window.RTCPeerConnection = window.webkitRTCPeerConnection;
      } else {
        alert('this browser does not support WebRTC.');
      }
    }

    if (!window.RTCSessionDescription) {
      if (window.mozRTCSessionDescription) {
        window.RTCSessionDescription = window.mozRTCSessionDescription;
      }
    }

    if (!window.RTCIceCandidate) {
      if (window.mozRTCIceCandidate) {
        window.RTCIceCandidate = window.mozRTCIceCandidate;
      }
    }

    //wrap functions to navigator for Chrome and Firefox
    if (!navigator.getUserMedia) {
      if (navigator.mozGetUserMedia) {
        navigator.getUserMedia = navigator.mozGetUserMedia;
      } else if (navigator.webkitGetUserMedia) {
        navigator.getUserMedia = navigator.webkitGetUserMedia;
      }
    }
    if (!window.AudioContext) {
      if (window.webkitAudioContext) {
        window.AudioContext = window.webkitAudioContext;
      }
    }
  }
  function onerror(e) {
    console.error(e);
  }
  function arrayToList(array, f) {
    var list = {ctor: "[]"};
    for(var i = array.length - 1; i >= 0; i--) {
      list = {
        ctor: "::",
        _0: f(array[i]),
        _1: list
      };
    }
    return list;
  }
  function listToArray(list) {
		var array = [];
		while (list.ctor !== '[]') {
			var entry = list._0;
      array.push(entry);
			list = list._1;
		}
		return array;
	}

  polyfill();

})();
<commit_msg>test2<commit_after>(function() {

  function Tuple3(x,y,z) {
		return {
			ctor: "_Tuple3",
			_0: x,
			_1: y,
      _2: z
		};
	}

  Elm.Native.WebRTC = {};

  Elm.Native.WebRTC.make = function(localRuntime) {
    localRuntime.Native = localRuntime.Native || {};
    localRuntime.Native.WebRTC = localRuntime.Native.WebRTC || {};
    if (localRuntime.Native.WebRTC.values) return localRuntime.Native.WebRTC.values;

    var Task = Elm.Native.Task.make(localRuntime);
    var Utils = Elm.Native.Utils.make(localRuntime);
    var NS = Elm.Native.Signal.make(localRuntime);
    var requests = NS.input('WebRTC.requests', Tuple3("", "", ""));
    var _onLocalVideoURL = NS.input('WebRTC.onLocalVideoURL', Utils.Tuple2("", ""));
    var _onRemoteVideoURL = NS.input('WebRTC.onRemoteVideoURL', Utils.Tuple2(Utils.Tuple2("", ""), ""));
    var _onAddConnection = NS.input('WebRTC.onAddConnection',  Utils.Tuple2("", ""));
    var _onRemoveConnection = NS.input('WebRTC.onRemoveConnection',  Utils.Tuple2("", ""));

    //TODO
    var cm = null;
    var clientId = null;
    var room = getRoom();//TODO

    var _initialize = function(_clientId, iceServers) {
      iceServers = listToArray(iceServers);
      clientId = _clientId;
      cm = createConnectionManager({
        iceServers: iceServers
      });
      return Task.asyncFunction(function(callback) {
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var send = function(data) {
      data.room = room;
      data.from = clientId;
      console.log('RTC send: ' + data.type);
      setTimeout(function() {
        localRuntime.notify(requests.id, Tuple3(data.type, data.to || "", data.data));
      });
    };

    var _answerSDP = function(from, data) {
      return Task.asyncFunction(function(callback) {
        answerSDP(clientId, cm, send, {
          from: from,
          data: data
        }, function onRemoteVideoURL(from, mediaType, url) {
          setTimeout(function() {
            localRuntime.notify(_onRemoteVideoURL.id, Utils.Tuple2(Utils.Tuple2(from, mediaType), url));
          });
        }, function onAddConnection(from, mediaType) {
          setTimeout(function() {
            localRuntime.notify(_onAddConnection.id, Utils.Tuple2(from, mediaType));
          });
        }, function onRemoveConnection(from, mediaType) {
          setTimeout(function() {
            localRuntime.notify(_onRemoveConnection.id, Utils.Tuple2(from, mediaType));
          });
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _acceptAnswer = function(from, data) {
      return Task.asyncFunction(function(callback) {
        acceptAnswer(clientId, cm, send, {
          from: from,
          data: data
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _addCandidate = function(from, data) {
      return Task.asyncFunction(function(callback) {
        addCandidate(clientId, cm, send, {
          from: from,
          data: data
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _closeRemoteStream = function(from, data) {
      return Task.asyncFunction(function(callback) {
        console.log(data);
        closeRemoteStream(cm, from, data.mediaType, function onRemoteVideoURL(from, mediaType, url) {
          localRuntime.setTimeout(function(){
            localRuntime.notify(_onRemoteVideoURL.id, Utils.Tuple2(Utils.Tuple2(from, mediaType), url));
          }, 0);
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _startStreaming = function(mediaType, peers) {
      peers = listToArray(peers);
      return Task.asyncFunction(function(callback) {
        offerSDP(clientId, cm, send, mediaType, peers, function onLocalVideoURL(mediaType, url) {
          // console.log([mediaType, url]);
          localRuntime.notify(_onLocalVideoURL.id, Utils.Tuple2(mediaType, url));
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var _endStreaming = function(mediaType) {
      return Task.asyncFunction(function(callback) {
        localRuntime.setTimeout(function() {
          localRuntime.notify(_onLocalVideoURL.id, Utils.Tuple2(mediaType, ""));
        }, 0);
        endStreaming(clientId, cm, send, mediaType);
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var beforeJoin = function(peerId) {
      return Task.asyncFunction(function(callback) {
        join(clientId, cm, send, peerId);
        callback(Task.succeed(Utils.Tuple0));
      });
    };
    var beforeLeave = function(peerId) {
      return Task.asyncFunction(function(callback) {
        leave(clientId, cm, send, peerId, function onRemoteVideoURL(from, mediaType, url) {
          localRuntime.setTimeout(function() {
            localRuntime.notify(_onRemoteVideoURL.id, Utils.Tuple2(Utils.Tuple2(from, mediaType), url));
          }, 0);
        });
        callback(Task.succeed(Utils.Tuple0));
      });
    };

    var currentVolumes = function() {
      var array = cm ? cm.getCurrentVolumes() : [];
      var list = arrayToList(array, function(peerId_volume) {
        return Utils.Tuple2(peerId_volume[0], peerId_volume[1]);
      });
      return list;
    };

    return localRuntime.Native.WebRTC.values = {
      initialize: F2(_initialize),
      answerSDP: F2(_answerSDP),
      acceptAnswer: F2(_acceptAnswer),
      addCandidate: F2(_addCandidate),
      closeRemoteStream: F2(_closeRemoteStream),
      startStreaming: F2(_startStreaming),
      endStreaming: _endStreaming,
      beforeJoin: beforeJoin,
      beforeLeave: beforeLeave,
      requests: requests,
      onLocalVideoURL: _onLocalVideoURL,
      onRemoteVideoURL: _onRemoteVideoURL,
      onAddConnection: _onAddConnection,
      onRemoveConnection: _onRemoveConnection,
      currentVolumes: currentVolumes
    };
  };
  function getRoom() {
    var roomId = decodeURI(location.href.split('/room/')[1].split('?')[0]);
    return roomId;
  }

  function createConnectionManager(connectionOption) {
    var connections = {};//TODO upstream/downstream
    var getConnection = function(id) {
      if(!id) {
        throw new Error('id is null');
      }
      if (!connections[id]) {
        console.log('not exists: ' + id);
        var pc = new RTCPeerConnection(connectionOption);
        connections[id] = pc;
      }
      return connections[id];
    };
    var getAllConnections = function() {
      return Object.keys(connections).map(function(key) {
        return connections[key];
      });
    };
    var removeConnection = function(peerId) {
      delete connections[peerId];
    };
    var removeAllConnections = function(){
      connections = {};
    };

    //----
    var streams = {};
    var audioAnalysers = {};
    var addStream = function(peerId, mediaType, stream) {

      if(window.AudioContext && mediaType === 'mic') {
        setTimeout(function(){
          var context = new AudioContext();
          var source = context.createMediaStreamSource(stream);
          var gainNode = context.createGain();
          gainNode.gain.value = 100.0;

          var analyser = context.createAnalyser();
          // analyser.fftSize = 1024;
          source.connect(gainNode);
          gainNode.connect(analyser);
          // alert(analyser.minDecibels);
          // alert(analyser.maxDecibels);
          // analyser.minDecibel = -40;
          // analyser.maxDecibels = -10;
          // analyser.minDecibels = parseFloat(document.getElementById("min").value);
          // analyser.maxDecibels = parseFloat(document.getElementById("max").value);
          // analyser.smoothingTimeConstant = parseFloat(document.getElementById("smoothing").value);
          audioAnalysers[peerId] = analyser;
        }, 100)

      }
      streams[peerId + mediaType] = stream;
    };
    var getCurrentVolumes = function() {
      var all = Object.keys(audioAnalysers).map(function(peerId) {
        var analyser = audioAnalysers[peerId];
        var data = new Uint8Array(analyser.frequencyBinCount);
        analyser.getByteTimeDomainData(data);
        var sum = 0;
        for(var i = 0; i < data.length; i++) {
          var value = data[i] - 128;
          sum += value > 0 ? value : -value;
        }
        var value = Math.round(sum / data.length);
        return [peerId, value];
      });
      return all;
    };
    var getStream = function(peerId, mediaType) {
      return streams[peerId + mediaType];
    };
    var removeStream = function(peerId, mediaType) {
      delete streams[peerId + mediaType];
    };
    return {
      getConnection: getConnection,
      getAllConnections: getAllConnections,
      removeConnection: removeConnection,
      removeAllConnections: removeAllConnections,
      getStream: getStream,
      addStream: addStream,
      removeStream: removeStream,
      getCurrentVolumes: getCurrentVolumes
    };
  }

  function offerSDP(clientId, cm, send, mediaType, peers, onLocalVideoURL) {
    var mediaOptions = {};
    if(mediaType === 'mic') {
      mediaOptions.audio = true;
      f(mediaOptions);
    } else if(mediaType === 'video') {
      mediaOptions.video = true;
      f(mediaOptions);
    } else if(mediaType === 'screen') {
      getScreenId(function (error, sourceId, mediaOptions) {
        if(error === 'not-installed') {
          alert('Screen Capturing is not installed.');
          return;
        } else if(error === 'installed-disabled') {
          alert('Screen Capturing is installed but disabled.');
          return;
        } else {
          f(mediaOptions);
        }
      });
    }

    function f(mediaOptions) {
      navigator.getUserMedia(mediaOptions, function(stream) {
        console.log(stream);
        console.log(stream.getAudioTracks());
        console.log(stream.getVideoTracks());

        cm.addStream(clientId, mediaType, stream);
        peers.forEach(function(peerId) {
          sendOfferToPeer(clientId, cm, send, peerId, stream, mediaType);
        });
        onLocalVideoURL(mediaType, URL.createObjectURL(stream));

      }, onerror);
    }

  }

  function sendOfferToPeer(clientId, cm, send, peerId, stream, mediaType) {
    if(peerId === clientId) {
      return;
    }
    var pc = cm.getConnection(peerId);
    pc.onicecandidate = function(e) {
      if (e.candidate) {
        setTimeout(function(){
          send({
            type: 'offerCandidate',
            to: peerId,
            data: e.candidate
          });
        }, 2000);
      }
    };

    pc.addStream(stream);

    pc.createOffer(function(offer) {
      // console.log('created offer', offer);

      pc.setLocalDescription(
        new RTCSessionDescription(offer),
        function() { // send offer to server
          send({
            type: 'offerSDP',
            to: peerId,
            data: {
              offer: offer,
              mediaType: mediaType
            }
          });
        }, onerror);
    }, onerror);
  }

  function answerSDP(clientId, cm, send, e, onRemoteVideoURL, onAddConnection, onRemoveConnection) {
    var _from = e.from;
    var pc = cm.getConnection(_from);
    var mediaType = e.data.mediaType;
    pc.onicecandidate = function(e) {
      if (e.candidate) {
        send({
          type: 'answerCandidate',
          to: _from,
          data: e.candidate
        });
      }
    };
    pc.onaddstream = function(e) {
      var mediaType = e.getAudioTracks()[0] ? 'mic' : 'video';//TODO
      cm.addStream(_from, mediaType, e.stream);
      onRemoteVideoURL(_from, mediaType, URL.createObjectURL(e.stream));
    };
    pc.onremovestream = function(e) {
      console.log('onremovestream');
      // console.log(e);
      // cm.removeStream(_from, mediaType);
      // onRemoveConnection(_from, mediaType);
    };
    onAddConnection(_from, mediaType);
    pc.setRemoteDescription(
      new RTCSessionDescription(e.data.offer),
      function() {
        pc.createAnswer(function(answer) {
          pc.setLocalDescription(
            new RTCSessionDescription(answer),
            function() {
              send({
                type: 'answerSDP',
                to: e.from,
                data: answer
              });
            }, onerror);
        }, onerror);
      }, onerror);
  }

  function acceptAnswer(clientId, cm, send, e) {
    var pc = cm.getConnection(e.from);
    pc.setRemoteDescription(
      new RTCSessionDescription(e.data),
      function() {
      },
      onerror);
  };

  function addCandidate(clientId, cm, send, e) {
    var pc = cm.getConnection(e.from);
    console.log('addCandidate:', JSON.stringify(e.data));
    if (e.data.candidate) {
      pc.addIceCandidate(new RTCIceCandidate(e.data));
    }
  }

  function endStreaming(clientId, cm, send, mediaType) {
    var stream = cm.getStream(clientId, mediaType);
    console.log(cm.getAllConnections(), mediaType);
    cm.getAllConnections().forEach(function(pc) {
      try {
        console.log(stream);
        pc.removeStream(stream);
      } catch(e) {
        console.error(e);
      }
    });
    cm.removeStream(clientId, mediaType);
    send({
      type: 'endStream',
      to: clientId,
      data: {
        mediaType: mediaType
      }
    });
  }

  // connect curent streams to joined peer
  function join(clientId, cm, send, from) {
    ["mic", "video", "screen"].forEach(function(mediaType) {
      var stream = cm.getStream(clientId, mediaType);
      if(stream) {
        sendOfferToPeer(clientId, cm, send, from, stream, mediaType);
      }
    });
  }
  // unconnect curent streams to joined peer
  function leave(clientId, cm, send, from, onRemoteVideoURL) {
    cm.removeConnection(from);
    ["mic", "video", "screen"].forEach(function(mediaType) {
      closeRemoteStream(cm, from, mediaType, onRemoteVideoURL);
    });
  }

  function closeRemoteStream(cm, remoteClientId, mediaType, onRemoteVideoURL) {
    var pc = cm.getConnection(remoteClientId);
    var stream = cm.getStream(remoteClientId, mediaType);
    if(stream) {
      pc.removeStream(stream);
      cm.removeStream(remoteClientId, mediaType);
    }
    onRemoteVideoURL(remoteClientId, mediaType, "");
  }

  function polyfill() {
    if (!window.RTCPeerConnection) {
      if (window.mozRTCPeerConnection) {
        window.RTCPeerConnection = window.mozRTCPeerConnection;
      } else if (window.webkitRTCPeerConnection) {
        window.RTCPeerConnection = window.webkitRTCPeerConnection;
      } else {
        alert('this browser does not support WebRTC.');
      }
    }

    if (!window.RTCSessionDescription) {
      if (window.mozRTCSessionDescription) {
        window.RTCSessionDescription = window.mozRTCSessionDescription;
      }
    }

    if (!window.RTCIceCandidate) {
      if (window.mozRTCIceCandidate) {
        window.RTCIceCandidate = window.mozRTCIceCandidate;
      }
    }

    //wrap functions to navigator for Chrome and Firefox
    if (!navigator.getUserMedia) {
      if (navigator.mozGetUserMedia) {
        navigator.getUserMedia = navigator.mozGetUserMedia;
      } else if (navigator.webkitGetUserMedia) {
        navigator.getUserMedia = navigator.webkitGetUserMedia;
      }
    }
    if (!window.AudioContext) {
      if (window.webkitAudioContext) {
        window.AudioContext = window.webkitAudioContext;
      }
    }
  }
  function onerror(e) {
    console.error(e);
  }
  function arrayToList(array, f) {
    var list = {ctor: "[]"};
    for(var i = array.length - 1; i >= 0; i--) {
      list = {
        ctor: "::",
        _0: f(array[i]),
        _1: list
      };
    }
    return list;
  }
  function listToArray(list) {
		var array = [];
		while (list.ctor !== '[]') {
			var entry = list._0;
      array.push(entry);
			list = list._1;
		}
		return array;
	}

  polyfill();

})();
<|endoftext|>


<commit_before>var Period = require('./Period');
var Time = require('./Time');

function PeriodFactory() {
    this.teamA;
    this.teamB;
    this.seed;
}

PeriodFactory.prototype = {

    setTeamA: function (teamA) {
        var periodFactory = new PeriodFactory();

        periodFactory.teamA = teamA;
        periodFactory.teamB = this.teamB;
        periodFactory.seed = this.seed;

        return periodFactory;
    },

    setTeamB: function (teamB) {
        var periodFactory = new PeriodFactory();

        periodFactory.teamA = this.teamA;
        periodFactory.teamB = teamB;
        periodFactory.seed = this.seed;

        return periodFactory;
    },

    setSeed: function (seed) {
        var periodFactory = new PeriodFactory();

        periodFactory.teamA = this.teamA;
        periodFactory.teamB = this.teamB;
        periodFactory.seed = seed;

        return periodFactory;
    },

    create: function (options) {
        return new Period({
            teamA: this.teamA,
            teamB: this.teamB,
            seed: this.seed.append(options.seed),
            timeLength: new Time().setMinutes(options.minutesLength),
            previousPeriod: options.previousPeriod,
            startDate:
                new Time()
                    .setMinutes(options.minutesAfterPrevious)
                    .addToDate(options.previousPeriod.finishDate)
        });
    },

    createFirstHalf: function (seed, previousPeriod) {
        return new Period({
            timeLength: new Time().setMinutes(45),
            seed: seed.append('firstHalf')
        });
    },

    createSecondHalf: function (seed, previousPeriod) {

    },

    createFirstHalfET: function (seed, previousPeriod) {

    },

    createSecondHalfET: function (seed, previousPeriod) {

    }

};

module.exports = PeriodFactory;
<commit_msg>Refactors PeriodFactory create<commit_after>var Period = require('./Period');
var Time = require('./Time');

function PeriodFactory() {
    this.teamA;
    this.teamB;
    this.seed;
}

PeriodFactory.prototype = {

    setTeamA: function (teamA) {
        var periodFactory = new PeriodFactory();

        periodFactory.teamA = teamA;
        periodFactory.teamB = this.teamB;
        periodFactory.seed = this.seed;

        return periodFactory;
    },

    setTeamB: function (teamB) {
        var periodFactory = new PeriodFactory();

        periodFactory.teamA = this.teamA;
        periodFactory.teamB = teamB;
        periodFactory.seed = this.seed;

        return periodFactory;
    },

    setSeed: function (seed) {
        var periodFactory = new PeriodFactory();

        periodFactory.teamA = this.teamA;
        periodFactory.teamB = this.teamB;
        periodFactory.seed = seed;

        return periodFactory;
    },

    create: function (options) {
        var time = new Time();

        return new Period({
            teamA: this.teamA,
            teamB: this.teamB,
            seed: this.seed.append(options.seed),
            timeLength: time.setMinutes(options.minutesLength),
            previousPeriod: options.previousPeriod,
            startDate:
                time
                    .setMinutes(options.minutesAfterPrevious)
                    .addToDate(options.previousPeriod.finishDate)
        });
    },

    createFirstHalf: function (seed, previousPeriod) {
        return new Period({
            timeLength: new Time().setMinutes(45),
            seed: seed.append('firstHalf')
        });
    },

    createSecondHalf: function (seed, previousPeriod) {

    },

    createFirstHalfET: function (seed, previousPeriod) {

    },

    createSecondHalfET: function (seed, previousPeriod) {

    }

};

module.exports = PeriodFactory;
<|endoftext|>


<commit_before>'use strict';

var Particle = require('./bodies/Particle');
var Constraint = require('./constraints/Constraint');
var Force = require('./forces/Force');

var Vec3 = require('famous-math').Vec3;
var Quaternion = require('famous-math').Quaternion;

var VEC_REGISTER = new Vec3();
var XYZ_REGISTER = new Vec3();
var QUAT_REGISTER = new Quaternion();
var DELTA_REGISTER = new Vec3();

/**
 * Singleton PhysicsEngine object.
 * Manages bodies, forces, constraints.
 *
 * @class PhysicsEngine
 * @param {Object} options A hash of configurable options.
 */
function PhysicsEngine(options) {
    options = options || {};
    /** @prop bodies The bodies currently active in the engine. */
    this.bodies = [];
    /** @prop forces The forces currently active in the engine. */
    this.forces = [];
    /** @prop constraints The constraints currently active in the engine. */
    this.constraints = [];

    /** @prop step The time between frames in the engine. */
    this.step = options.step || 1000/60;
    /** @prop iterations The number of times each constraint is solved per frame. */
    this.iterations = options.iterations || 10;
    /** @prop _indexPool Pools of indicies to track holes in the arrays. */
    this._indexPools = {
        bodies: [],
        forces: [],
        constraints: []
    };

    this._entityMaps = {
        bodies: {},
        forces: {},
        constraints: {}
    };

    this.speed = options.speed || 1.0;
    this.time = 0;
    this.delta = 0;

    this.origin = options.origin || new Vec3();
    this.orientation = options.orientation ? options.orientation.normalize() :  new Quaternion();

    this.prestep = [];
    this.poststep = [];

    this.buffer = {
        position: [0, 0, 0],
        rotation: [0, 0, 0],
        size: [0, 0, 0]
    };

    this.frameDependent = options.frameDependent || false;
}

/**
 * Set the origin of the world.
 *
 * @method setOrigin
 * @chainable
 * @param {Number} x The x component.
 * @param {Number} y The y component.
 * @param {Number} z The z component.
 */
PhysicsEngine.prototype.setOrigin = function(x, y, z) {
    this.origin.set(x, y, z);
    return this;
};

/**
 * Set the orientation of the world.
 *
 * @method setOrientation
 * @chainable
 * @param {Number} w The w component.
 * @param {Number} x The x component.
 * @param {Number} y The y component.
 * @param {Number} z The z component.
 */
PhysicsEngine.prototype.setOrientation = function(w, x, y, z) {
    this.orientation.set(w, x, y, z).normalize();
    return this;
}

/**
 * Private helper method to store an element in a library array.
 *
 * @method _addElement
 * @private
 * @param {Object} element The body, force, or constraint to add.
 * @param {String} key Where to store the element.
 */
function _addElement(context, element, key) {
    var map = context._entityMaps[key];
    if (map[element._ID] == null) {
        var library = context[key];
        var indexPool = context._indexPools[key];
        if (indexPool.length) map[element._ID] = indexPool.pop();
        else map[element._ID] = library.length;
        library[map[element._ID]] = element;
    }
}

/**
 * Private helper method to remove an element from a library array.
 *
 * @method _removeElement
 * @private
 * @param {Object} element The body, force, or constraint to remove.
 * @param {String} key Where to store the element.
 */
function _removeElement(context, element, key) {
    var map = context._entityMaps[key];
    var index = map[element._ID];
    if (index != null) {
        context._indexPools[key].push(index);
        context[key][index] = null;
        map[element._ID] = null;
    }
}

/**
 * Add a group of bodies, force, or constraints to the engine.
 *
 * @method add
 * @chainable
 */
PhysicsEngine.prototype.add = function add() {
    for (var j = 0, lenj = arguments.length; j < lenj; j++) {
        var entity = arguments[j];
        if (entity instanceof Array) {
            for (var i = 0, len = entity.length; i < len; i++) {
                var e = entity[i];
                this.add(e);
            }
        } else {
            if (entity instanceof Particle) this.addBody(entity);
            else if (entity instanceof Constraint) this.addConstraint(entity);
            else if (entity instanceof Force) this.addForce(entity);
        }
    }
    return this;
};

/**
 * Remove a group of bodies, force, or constraints from the engine.
 *
 * @method remove
 * @chainable
 */
PhysicsEngine.prototype.remove = function remove() {
    for (var j = 0, lenj = arguments.length; j < lenj; j++) {
        var entity = arguments[j];
        if (entity instanceof Array) {
            for (var i = 0, len = entity.length; i < len; i++) {
                var e = entity[i];
                this.add(e);
            }
        } else {
            if (entity instanceof Particle) this.removeBody(entity);
            else if (entity instanceof Constraint) this.removeConstraint(entity);
            else if (entity instanceof Force) this.removeForce(entity);
        }
    }
    return this;
};

/**
 * Begin tracking a body.
 *
 * @method addBody
 * @param {Particle} body The body to track.
 */
PhysicsEngine.prototype.addBody = function addBody(body) {
    _addElement(this, body, 'bodies');
};

/**
 * Begin tracking a force.
 *
 * @method addForce
 * @param {Force} force The force to track.
 */
PhysicsEngine.prototype.addForce = function addForce(force) {
    _addElement(this, force, 'forces');
};

/**
 * Begin tracking a constraint.
 *
 * @method addConstraint
 * @param {Constraint} constraint The constraint to track.
 */
PhysicsEngine.prototype.addConstraint = function addConstraint(constraint) {
    _addElement(this, constraint, 'constraints');
};

/**
 * Stop tracking a body.
 *
 * @method removeBody
 * @param {Particle} body The body to stop tracking.
 */
PhysicsEngine.prototype.removeBody = function removeBody(body) {
    _removeElement(this, body, 'bodies')
};

/**
 * Stop tracking a force.
 *
 * @method removeForce
 * @param {Force} force The force to stop tracking.
 */
PhysicsEngine.prototype.removeForce = function removeForce(force) {
    _removeElement(this, force, 'forces')
};

/**
 * Stop tracking a constraint.
 *
 * @method removeConstraint
 * @param {Constraint} constraint The constraint to stop tracking.
 */
PhysicsEngine.prototype.removeConstraint = function removeConstraint(constraint) {
    _removeElement(this, constraint, 'constraints')
};

/**
 * Update the physics system to reflect the changes since the last frame. Steps forward in increments of
 * PhysicsEngine.step.
 *
 * @method update
 * @param {Number} time
 */
PhysicsEngine.prototype.update = function update(time) {
    if (this.time === 0) this.time = time;

    var bodies = this.bodies;
    var forces = this.forces;
    var constraints = this.constraints;

    var frameDependent = this.frameDependent;
    var step = this.step;
    var dt = step * 0.001;
    var speed = this.speed;

    var delta = this.delta;
    delta += (time - this.time) * speed;
    this.time = time;

    while(delta > step) {
        for (var i = 0, len = this.prestep.length; i < len; i++) {
            this.prestep[i](time, dt);
        }

        // Update Forces on particles
        for (var i = 0, numForces = forces.length; i < numForces; i++) {
            var force = forces[i];
            if (force === null) continue;
            force.update(time, dt);
        }

        // Tentatively update velocities
        for (var i = 0, numBodies = bodies.length; i < numBodies; i++) {
            var body = bodies[i];
            if (body === null) continue;
            _integrateVelocity(body, dt);
        }

        // Prep constraints for solver
        for (var i = 0, numConstraints = constraints.length; i < numConstraints; i++) {
            var constraint = constraints[i];
            if (constraint === null) continue;
            constraint.update(time, dt);
        }

        // Iteratively resolve constraints
        for (var j = 0, numIterations = this.iterations; j < numIterations; j++) {
            for (var i = 0; i < numConstraints; i++) {
                var constraint = constraints[i];
                if (constraint === null) continue;
                constraint.resolve(time, dt);
            }
        }

        // Increment positions and orientations
        for (var i = 0; i < numBodies; i++) {
            var body = bodies[i];
            if (body === null) continue;
            _integratePose(body, dt);
        }

        for (var i = 0, len = this.poststep.length; i < len; i++) {
            this.poststep[i](time, dt);
        }

        if (frameDependent) delta = 0;
        else delta -= step;
    }

    this.delta = delta;
};

/**
 * Get the transform equivalent to the Particle's position and orientation.
 *
 * @method getTransform
 * @return {Transform}
 */
PhysicsEngine.prototype.getTransform = function getTransform(body) {
    var o = this.origin;
    var oq = this.orientation;

    var p = body.position;
    var s = body.size;
    var q = body.orientation;
    var rot = q;
    var loc = p;
    if (oq.w !== 1) {
        rot = Quaternion.multiply(q, oq, QUAT_REGISTER)
        loc = oq.rotateVector(p, VEC_REGISTER);
    }
    var XYZ = rot.toEulerXYZ(XYZ_REGISTER);

    this.buffer.position[0] = o.x+loc.x;
    this.buffer.position[1] = o.y+loc.y;
    this.buffer.position[2] = o.z+loc.z;

    this.buffer.rotation[0] = XYZ.x;
    this.buffer.rotation[1] = XYZ.y;
    this.buffer.rotation[2] = XYZ.z;

    return this.buffer;
};

/**
 * Update the Particle momenta based off of current incident force and torque.
 *
 * @method _integrateVelocity
 * @private
 * @param {Particle} body
 * @param {Number} dt delta time
 */
function _integrateVelocity(body, dt) {
    body.momentum.add(Vec3.scale(body.force, dt, DELTA_REGISTER));
    body.angularMomentum.add(Vec3.scale(body.torque, dt, DELTA_REGISTER));
    Vec3.scale(body.momentum, body.inverseMass, body.velocity);
    body.inverseInertia.vectorMultiply(body.angularMomentum, body.angularVelocity);
    body.force.clear();
    body.torque.clear();
};

/**
 * Update the Particle position and orientation based off current translational and angular velocities.
 *
 * @method _integratePose
 * @private
 * @param {Particle} body
 * @param dt {Number} delta time
 */
function _integratePose(body, dt) {
    if (body.restrictions !== 0) {
        var restrictions = body.restrictions;
        var x = null;
        var y = null;
        var z = null;
        var ax = null;
        var ay = null;
        var az = null;

        if (restrictions & 32) x = 0;
        if (restrictions & 16) y = 0;
        if (restrictions & 8) z = 0;
        if (restrictions & 4) ax = 0;
        if (restrictions & 2) ay = 0;
        if (restrictions & 1) az = 0;

        body.setVelocity(x,y,z);
        body.setAngularVelocity(ax, ay, az);
    }

    body.position.add(Vec3.scale(body.velocity, dt, DELTA_REGISTER));

    var w = body.angularVelocity;
    var q = body.orientation;
    var wx = w.x;
    var wy = w.y;
    var wz = w.z;

    var qw = q.w;
    var qx = q.x;
    var qy = q.y;
    var qz = q.z;

    var hdt = dt * 0.5;
    q.w += (-wx * qx - wy * qy - wz * qz) * hdt;
    q.x += (wx * qw + wy * qz - wz * qy) * hdt;
    q.y += (wy * qw + wz * qx - wx * qz) * hdt;
    q.z += (wz * qw + wx * qy - wy * qx) * hdt;

    q.normalize();
};

module.exports = PhysicsEngine;
<commit_msg>chore: clean up of stale values<commit_after>'use strict';

var Particle = require('./bodies/Particle');
var Constraint = require('./constraints/Constraint');
var Force = require('./forces/Force');

var Vec3 = require('famous-math').Vec3;
var Quaternion = require('famous-math').Quaternion;

var VEC_REGISTER = new Vec3();
var XYZ_REGISTER = new Vec3();
var QUAT_REGISTER = new Quaternion();
var DELTA_REGISTER = new Vec3();

/**
 * Singleton PhysicsEngine object.
 * Manages bodies, forces, constraints.
 *
 * @class PhysicsEngine
 * @param {Object} options A hash of configurable options.
 */
function PhysicsEngine(options) {
    options = options || {};
    /** @prop bodies The bodies currently active in the engine. */
    this.bodies = [];
    /** @prop forces The forces currently active in the engine. */
    this.forces = [];
    /** @prop constraints The constraints currently active in the engine. */
    this.constraints = [];

    /** @prop step The time between frames in the engine. */
    this.step = options.step || 1000/60;
    /** @prop iterations The number of times each constraint is solved per frame. */
    this.iterations = options.iterations || 10;
    /** @prop _indexPool Pools of indicies to track holes in the arrays. */
    this._indexPools = {
        bodies: [],
        forces: [],
        constraints: []
    };

    this._entityMaps = {
        bodies: {},
        forces: {},
        constraints: {}
    };

    this.speed = options.speed || 1.0;
    this.time = 0;
    this.delta = 0;

    this.origin = options.origin || new Vec3();
    this.orientation = options.orientation ? options.orientation.normalize() :  new Quaternion();

    this.prestep = [];
    this.poststep = [];

    this.transformBuffer = {
        position: [0, 0, 0],
        rotation: [0, 0, 0]
    };

    this.frameDependent = options.frameDependent || false;
}

/**
 * Set the origin of the world.
 *
 * @method setOrigin
 * @chainable
 * @param {Number} x The x component.
 * @param {Number} y The y component.
 * @param {Number} z The z component.
 */
PhysicsEngine.prototype.setOrigin = function(x, y, z) {
    this.origin.set(x, y, z);
    return this;
};

/**
 * Set the orientation of the world.
 *
 * @method setOrientation
 * @chainable
 * @param {Number} w The w component.
 * @param {Number} x The x component.
 * @param {Number} y The y component.
 * @param {Number} z The z component.
 */
PhysicsEngine.prototype.setOrientation = function(w, x, y, z) {
    this.orientation.set(w, x, y, z).normalize();
    return this;
}

/**
 * Private helper method to store an element in a library array.
 *
 * @method _addElement
 * @private
 * @param {Object} element The body, force, or constraint to add.
 * @param {String} key Where to store the element.
 */
function _addElement(context, element, key) {
    var map = context._entityMaps[key];
    if (map[element._ID] == null) {
        var library = context[key];
        var indexPool = context._indexPools[key];
        if (indexPool.length) map[element._ID] = indexPool.pop();
        else map[element._ID] = library.length;
        library[map[element._ID]] = element;
    }
}

/**
 * Private helper method to remove an element from a library array.
 *
 * @method _removeElement
 * @private
 * @param {Object} element The body, force, or constraint to remove.
 * @param {String} key Where to store the element.
 */
function _removeElement(context, element, key) {
    var map = context._entityMaps[key];
    var index = map[element._ID];
    if (index != null) {
        context._indexPools[key].push(index);
        context[key][index] = null;
        map[element._ID] = null;
    }
}

/**
 * Add a group of bodies, force, or constraints to the engine.
 *
 * @method add
 * @chainable
 */
PhysicsEngine.prototype.add = function add() {
    for (var j = 0, lenj = arguments.length; j < lenj; j++) {
        var entity = arguments[j];
        if (entity instanceof Array) {
            for (var i = 0, len = entity.length; i < len; i++) {
                var e = entity[i];
                this.add(e);
            }
        } else {
            if (entity instanceof Particle) this.addBody(entity);
            else if (entity instanceof Constraint) this.addConstraint(entity);
            else if (entity instanceof Force) this.addForce(entity);
        }
    }
    return this;
};

/**
 * Remove a group of bodies, force, or constraints from the engine.
 *
 * @method remove
 * @chainable
 */
PhysicsEngine.prototype.remove = function remove() {
    for (var j = 0, lenj = arguments.length; j < lenj; j++) {
        var entity = arguments[j];
        if (entity instanceof Array) {
            for (var i = 0, len = entity.length; i < len; i++) {
                var e = entity[i];
                this.add(e);
            }
        } else {
            if (entity instanceof Particle) this.removeBody(entity);
            else if (entity instanceof Constraint) this.removeConstraint(entity);
            else if (entity instanceof Force) this.removeForce(entity);
        }
    }
    return this;
};

/**
 * Begin tracking a body.
 *
 * @method addBody
 * @param {Particle} body The body to track.
 */
PhysicsEngine.prototype.addBody = function addBody(body) {
    _addElement(this, body, 'bodies');
};

/**
 * Begin tracking a force.
 *
 * @method addForce
 * @param {Force} force The force to track.
 */
PhysicsEngine.prototype.addForce = function addForce(force) {
    _addElement(this, force, 'forces');
};

/**
 * Begin tracking a constraint.
 *
 * @method addConstraint
 * @param {Constraint} constraint The constraint to track.
 */
PhysicsEngine.prototype.addConstraint = function addConstraint(constraint) {
    _addElement(this, constraint, 'constraints');
};

/**
 * Stop tracking a body.
 *
 * @method removeBody
 * @param {Particle} body The body to stop tracking.
 */
PhysicsEngine.prototype.removeBody = function removeBody(body) {
    _removeElement(this, body, 'bodies')
};

/**
 * Stop tracking a force.
 *
 * @method removeForce
 * @param {Force} force The force to stop tracking.
 */
PhysicsEngine.prototype.removeForce = function removeForce(force) {
    _removeElement(this, force, 'forces')
};

/**
 * Stop tracking a constraint.
 *
 * @method removeConstraint
 * @param {Constraint} constraint The constraint to stop tracking.
 */
PhysicsEngine.prototype.removeConstraint = function removeConstraint(constraint) {
    _removeElement(this, constraint, 'constraints')
};

/**
 * Update the physics system to reflect the changes since the last frame. Steps forward in increments of
 * PhysicsEngine.step.
 *
 * @method update
 * @param {Number} time
 */
PhysicsEngine.prototype.update = function update(time) {
    if (this.time === 0) this.time = time;

    var bodies = this.bodies;
    var forces = this.forces;
    var constraints = this.constraints;

    var frameDependent = this.frameDependent;
    var step = this.step;
    var dt = step * 0.001;
    var speed = this.speed;

    var delta = this.delta;
    delta += (time - this.time) * speed;
    this.time = time;

    while(delta > step) {
        for (var i = 0, len = this.prestep.length; i < len; i++) {
            this.prestep[i](time, dt);
        }

        // Update Forces on particles
        for (var i = 0, numForces = forces.length; i < numForces; i++) {
            var force = forces[i];
            if (force === null) continue;
            force.update(time, dt);
        }

        // Tentatively update velocities
        for (var i = 0, numBodies = bodies.length; i < numBodies; i++) {
            var body = bodies[i];
            if (body === null) continue;
            _integrateVelocity(body, dt);
        }

        // Prep constraints for solver
        for (var i = 0, numConstraints = constraints.length; i < numConstraints; i++) {
            var constraint = constraints[i];
            if (constraint === null) continue;
            constraint.update(time, dt);
        }

        // Iteratively resolve constraints
        for (var j = 0, numIterations = this.iterations; j < numIterations; j++) {
            for (var i = 0; i < numConstraints; i++) {
                var constraint = constraints[i];
                if (constraint === null) continue;
                constraint.resolve(time, dt);
            }
        }

        // Increment positions and orientations
        for (var i = 0; i < numBodies; i++) {
            var body = bodies[i];
            if (body === null) continue;
            _integratePose(body, dt);
        }

        for (var i = 0, len = this.poststep.length; i < len; i++) {
            this.poststep[i](time, dt);
        }

        if (frameDependent) delta = 0;
        else delta -= step;
    }

    this.delta = delta;
};

/**
 * Get the transform equivalent to the Particle's position and orientation.
 *
 * @method getTransform
 * @return {Transform}
 */
PhysicsEngine.prototype.getTransform = function getTransform(body) {
    var o = this.origin;
    var oq = this.orientation;
    var p = body.position;
    var q = body.orientation;
    var rot = q;
    var loc = p;
    var XYZ;

    if (oq.w !== 1) {
        rot = Quaternion.multiply(q, oq, QUAT_REGISTER)
        loc = oq.rotateVector(p, VEC_REGISTER);
    }

    XYZ = rot.toEulerXYZ(XYZ_REGISTER);

    this.transformBuffer.position[0] = o.x+loc.x;
    this.transformBuffer.position[1] = o.y+loc.y;
    this.transformBuffer.position[2] = o.z+loc.z;

    this.transformBuffer.rotation[0] = XYZ.x;
    this.transformBuffer.rotation[1] = XYZ.y;
    this.transformBuffer.rotation[2] = XYZ.z;

    return this.transformBuffer;
};

/**
 * Update the Particle momenta based off of current incident force and torque.
 *
 * @method _integrateVelocity
 * @private
 * @param {Particle} body
 * @param {Number} dt delta time
 */
function _integrateVelocity(body, dt) {
    body.momentum.add(Vec3.scale(body.force, dt, DELTA_REGISTER));
    body.angularMomentum.add(Vec3.scale(body.torque, dt, DELTA_REGISTER));
    Vec3.scale(body.momentum, body.inverseMass, body.velocity);
    body.inverseInertia.vectorMultiply(body.angularMomentum, body.angularVelocity);
    body.force.clear();
    body.torque.clear();
};

/**
 * Update the Particle position and orientation based off current translational and angular velocities.
 *
 * @method _integratePose
 * @private
 * @param {Particle} body
 * @param dt {Number} delta time
 */
function _integratePose(body, dt) {
    if (body.restrictions !== 0) {
        var restrictions = body.restrictions;
        var x = null;
        var y = null;
        var z = null;
        var ax = null;
        var ay = null;
        var az = null;

        if (restrictions & 32) x = 0;
        if (restrictions & 16) y = 0;
        if (restrictions & 8) z = 0;
        if (restrictions & 4) ax = 0;
        if (restrictions & 2) ay = 0;
        if (restrictions & 1) az = 0;

        body.setVelocity(x,y,z);
        body.setAngularVelocity(ax, ay, az);
    }

    body.position.add(Vec3.scale(body.velocity, dt, DELTA_REGISTER));

    var w = body.angularVelocity;
    var q = body.orientation;
    var wx = w.x;
    var wy = w.y;
    var wz = w.z;

    var qw = q.w;
    var qx = q.x;
    var qy = q.y;
    var qz = q.z;

    var hdt = dt * 0.5;
    q.w += (-wx * qx - wy * qy - wz * qz) * hdt;
    q.x += (wx * qw + wy * qz - wz * qy) * hdt;
    q.y += (wy * qw + wz * qx - wx * qz) * hdt;
    q.z += (wz * qw + wx * qy - wy * qx) * hdt;

    q.normalize();
};

module.exports = PhysicsEngine;
<|endoftext|>


<commit_before>var PortfolioFIFO = function () {
    this.fifo = [];
}

PortfolioFIFO.prototype = {
    push: function (symbol, amount, price) {
        if (!(symbol in this.fifo)) {
            this.fifo[symbol] = [];
        }
        this.fifo[symbol].push({amount: parseInt(amount), price: parseFloat(price).toFixed(2), close: undefined});
    },

    pop: function (symbol, amount) {
        if (!(symbol in this.fifo)) {
            return;
        }
        amount = parseInt(amount);

        while (amount > 0) {
            if (this.fifo[symbol].length == 0) {
                return;
            }

            var a = this.fifo[symbol][0].amount;
            if (a <= amount) {
                amount -= a;
                this.fifo[symbol].shift();
            } else {
                a -= amount;
                amount = 0;
                this.fifo[symbol][0].amount = a;
            }
        }
    },

    cost: function () {
        var cost = 0;
        for (var key in this.fifo) {
            cost += this.costForStock(key);
        }
        return cost;
    },

    costForStock: function (symbol) {
        var data = this.fifo[symbol];
        if (data == undefined) {
            return 0;
        }
        var cost = 0;
        for (var i = 0; i < data.length; i++) {
            cost += data[i].amount * data[i].price;
        }
        return cost;
    },

    amountOfStocks: function (symbol) {
        var data = this.fifo[symbol];
        if (data == undefined) {
            return 0;
        }
        var amount = 0;
        for (var i = 0; i < data.length; i++) {
            amount += data[i].amount;
        }
        return amount;
    },

    value: function () {
        var value = 0;
        for (var key in this.fifo) {
            value += this.valueForStock(key);
        }
        return value;
    },

    valueForStock: function (symbol) {
        var data = this.fifo[symbol];
        if (data == undefined) {
            return 0;
        }
        var value = 0;
        if(data.close != undefined) {
            for (var i = 0; i < data.length; i++) {
                value += data[i].amount * data.close;
            }
        }
        return value;
    },

    setClosePrice: function(symbol, closePrice) {
        this.fifo[symbol].close = closePrice;
    },

    clone: function () {
        return JSON.parse(JSON.stringify(this));
    },

    getStockAndClose: function() {
        var array = [];
        for(var key in this.fifo) {
            array[key] = this.fifo[key].close;
        }
        return array;
    }

}<commit_msg>Added validation for missing symbil<commit_after>var PortfolioFIFO = function () {
    this.fifo = [];
}

PortfolioFIFO.prototype = {
    push: function (symbol, amount, price) {
        if (!(symbol in this.fifo)) {
            this.fifo[symbol] = [];
        }
        this.fifo[symbol].push({amount: parseInt(amount), price: parseFloat(price).toFixed(2), close: undefined});
    },

    pop: function (symbol, amount) {
        if (!(symbol in this.fifo)) {
            return;
        }
        amount = parseInt(amount);

        while (amount > 0) {
            if (this.fifo[symbol].length == 0) {
                return;
            }

            var a = this.fifo[symbol][0].amount;
            if (a <= amount) {
                amount -= a;
                this.fifo[symbol].shift();
            } else {
                a -= amount;
                amount = 0;
                this.fifo[symbol][0].amount = a;
            }
        }
    },

    cost: function () {
        var cost = 0;
        for (var key in this.fifo) {
            cost += this.costForStock(key);
        }
        return cost;
    },

    costForStock: function (symbol) {
        var data = this.fifo[symbol];
        if (data == undefined) {
            return 0;
        }
        var cost = 0;
        for (var i = 0; i < data.length; i++) {
            cost += data[i].amount * data[i].price;
        }
        return cost;
    },

    amountOfStocks: function (symbol) {
        var data = this.fifo[symbol];
        if (data == undefined) {
            return 0;
        }
        var amount = 0;
        for (var i = 0; i < data.length; i++) {
            amount += data[i].amount;
        }
        return amount;
    },

    value: function () {
        var value = 0;
        for (var key in this.fifo) {
            value += this.valueForStock(key);
        }
        return value;
    },

    valueForStock: function (symbol) {
        var data = this.fifo[symbol];
        if (data == undefined) {
            return 0;
        }
        var value = 0;
        if(data.close != undefined) {
            for (var i = 0; i < data.length; i++) {
                value += data[i].amount * data.close;
            }
        }
        return value;
    },

    setClosePrice: function(symbol, closePrice) {
        if(symbol in this.fifo) {
            this.fifo[symbol].close = closePrice;
        }
    },

    clone: function () {
        return JSON.parse(JSON.stringify(this));
    },

    getStockAndClose: function() {
        var array = [];
        for(var key in this.fifo) {
            array[key] = this.fifo[key].close;
        }
        return array;
    }

}<|endoftext|>