<commit_before>// Models
import WorkLog_TYPE from './WorkLogType.js';
import UserType from '../User/UserType.js';
// GraphQL
import {
	GraphQLString,
	GraphQLList,
	GraphQLInt,
	GraphQLFloat,
	GraphQLObjectType
} from 'graphql';
// RethinkDB
import r from 'rethinkdb';
// Constants
import { DB_HOST, DB_PORT, ADMIN_ID,TESTER_ID } from '../../constants/configurations.js';
import moment from 'moment';

let WorkLogQuery = {
	'getWorkLogList': {
		type: new GraphQLList(UserType),
		description: 'Get all worklog',
        args: {
			startDate: {
				type: GraphQLFloat,
				description: 'the start date of the query'
			},
			dateRange: {
				type: GraphQLInt,
				description: 'the date range of the query'
			}
		},
		resolve: async (root, { startDate , dateRange}) => {
			let connection = null,
			    result = [],
				query = null;

			try {
				if(dateRange <= 0){
					return result;
				}
				let endDate = startDate + (dateRange -1) * 1000 * 3600 * 24;
				query = r.db('work_genius').table('users').filter(r.row('id').ne(ADMIN_ID).and(r.row('id').ne(TESTER_ID)))
					.pluck('id','name','location').coerceTo('array');
				connection = await r.connect({ host: DB_HOST, port: DB_PORT });
				//get all users
				let users = await query.run(connection);

				//get all PTO data
				query = r.db('work_genius').table('pto')
					.filter(r.row('status').eq('PENDING').or(r.row('status').eq('APPROVED')))
					.filter(r.row('hours').coerceTo('number').ge(8))
					.pluck('applicant_id','start_date','end_date','hours').coerceTo('array');
				let ptoList = await query.run(connection);

				//get all uncompleted worklog list
				query = r.db('work_genius').table('worklog')
					.filter(r.js('(function(row){ \
						return (row.start_date >= '+startDate+' && row.start_date <= '+endDate+') \
							|| (row.start_date < '+startDate+' && row.end_date >= '+startDate+' )\
						})'))
					.coerceTo('array');
				let worklogList = await query.run(connection);

				//get all dates and check if the date is weekend or not
				let dateList = [];
				for(let i=0; i < dateRange; i++){
					let tmpDate  = startDate + i * 1000 * 3600 * 24;
					dateList.push({
						date: tmpDate,
						day_type: [0,6].includes(moment(tmpDate).day())? 'holiday':'workday'
					});
				}

				//get all public holiday
				query = r.db('work_genius').table('holiday')
					.filter(r.row('date').ge(startDate)).coerceTo('array');
				let holidayList = await query.run(connection);

				//construct the result array
				for(let user of users){
					let userItem = {...user,worklogs:[]};
					for(let dateItem of dateList){
						userItem.worklogs.push(Object.assign({},dateItem));
					}

					userItem.worklogs.forEach(dateItem => {
						//set pto info
						let findPTO = ptoList.find( pto => {
							if(moment(pto.start_date).isSame(moment(pto.end_date))){
								return pto.applicant_id == user.id
									&& moment(dateItem.date).isSame(moment(pto.start_date));
							}else{
								return pto.applicant_id == user.id
									&& (moment(dateItem.date).isBetween(pto.start_date,pto.end_date)
										|| moment(dateItem.date).isSame(pto.start_date,'day')
										|| moment(dateItem.date).isSame(pto.end_date,'day'));
							}
						});
						if(!!findPTO){
							dateItem.day_type = 'pto';
						}

						//set public holiday info
						let findHoliday = holidayList.find( holiday => {
							return holiday.date == dateItem.date && holiday.location == userItem.location;
						});
						if(!!findHoliday){
							dateItem.day_type = findHoliday.type;
						}
					});

					//get all my worklog list
					let myWorkLogList = worklogList.filter(log => {
						return log.employee_id === userItem.id;
					});

					//assign the worklog to the proper date
					if(myWorkLogList && myWorkLogList.length > 0){
						myWorkLogList.forEach(log => {
							let tmpEndDate = endDate > log.end_date ? log.end_date : endDate;
							for(let date = startDate ; date <= tmpEndDate; date += 1000 * 60 * 60 * 24){
								let dateItem = userItem.worklogs.find(dateItem => {
									return dateItem.date == date;
								})
								if(dateItem && dateItem.day_type == 'workday'){
									dateItem.worklog_items = dateItem.worklog_items || [];
									dateItem.worklog_items.push(log);
								}
							}
						});
					}

					result.push(userItem);
				}
				await connection.close();
				return result;
			} catch (err) {
				return err;
			}
			return result;
		}
	},
	'getWorkLogByEmployeeId': {
		type: new GraphQLList(UserType),
		description: 'Get all worklog of selected user',
        args: {
			startDate: {
				type: GraphQLFloat,
				description: 'the start date of the query'
			},
			dateRange: {
				type: GraphQLInt,
				description: 'the date range of the query'
			},
			employeeId: {
				type: GraphQLString,
				description: 'the employee id'
			}
		},
		resolve: async (root, { startDate , dateRange , employeeId}) => {
			let connection = null,
				query = null,
			    result = [];

			try {
				let endDate = startDate + (dateRange -1) * 1000 * 3600 * 24;
				query = r.db('work_genius').table('users').get(employeeId)
					.pluck('id','name','location');
				connection = await r.connect({ host: DB_HOST, port: DB_PORT });
				//get all users
				let user = await query.run(connection);

				//get all PTO data
				query = r.db('work_genius').table('pto')
					.filter({'applicant_id':employeeId})
					.filter(r.row('status').eq('PENDING').or(r.row('status').eq('APPROVED')))
					.filter(r.row('hours').coerceTo('number').ge(8))
					.pluck('applicant_id','start_date','end_date','hours').coerceTo('array');
				let ptoList = await query.run(connection);

				//get all uncompleted worklog list
				query = r.db('work_genius').table('worklog')
					.filter({employee_id:employeeId})
					.filter(r.js('(function(row){ \
						return (row.start_date >= '+startDate+' && row.start_date <= '+endDate+') \
							|| (row.start_date < '+startDate+' && row.end_date >= '+startDate+' )\
						})'))
					.coerceTo('array');
				let worklogList = await query.run(connection);

				//get all dates and check if the date is weekend or not
				let dateList = [];
				for(let i=0; i < dateRange; i++){
					let tmpDate  = startDate + i * 1000 * 3600 * 24;
					dateList.push({
						date: tmpDate,
						day_type: [0,6].includes(moment(tmpDate).day())? 'holiday':'workday'
					});
				}

				//get all public holiday
				query = r.db('work_genius').table('holiday')
					.filter({location:user.location})
					.filter(r.row('date').ge(startDate)).coerceTo('array');
				let holidayList = await query.run(connection);

				//construct the result array
				let userItem = {...user,worklogs:[]};
				for(let dateItem of dateList){
					userItem.worklogs.push(Object.assign({},dateItem));
				}

				userItem.worklogs.forEach(dateItem => {
					//set pto info
					let findPTO = ptoList.find( pto => {
						if(moment(pto.start_date).isSame(moment(pto.end_date))){
							return pto.applicant_id == user.id
								&& moment(dateItem.date).isSame(moment(pto.start_date));
						}else{
							return pto.applicant_id == user.id
								&& (moment(dateItem.date).isBetween(pto.start_date,pto.end_date)
									|| moment(dateItem.date).isSame(pto.start_date,'day')
									|| moment(dateItem.date).isSame(pto.end_date,'day'));
						}
					});
					if(!!findPTO){
						dateItem.day_type = 'pto';
					}

					//set public holiday info
					let findHoliday = holidayList.find( holiday => {
						return holiday.date == dateItem.date && holiday.location == userItem.location;
					});
					if(!!findHoliday){
						dateItem.day_type = findHoliday.type;
					}
				});

				//get all my worklog list
				let myWorkLogList = worklogList.filter(log => {
					return log.employee_id === userItem.id;
				});

				//assign the worklog to the proper date
				if(myWorkLogList && myWorkLogList.length > 0){
					myWorkLogList.forEach(log => {
						let tmpEndDate = endDate > log.end_date ? log.end_date : endDate;
						for(let date = startDate ; date <= tmpEndDate; date += 1000 * 60 * 60 * 24){
							let dateItem = userItem.worklogs.find(dateItem => {
								return dateItem.date == date;
							})
							if(dateItem && dateItem.day_type == 'workday'){
								dateItem.worklog_items = dateItem.worklog_items || [];
								dateItem.worklog_items.push(log);
							}
						}
					});
				}

				result.push(userItem);

				await connection.close();
				return result;
			} catch (err) {
				return err;
			}
			return result;
		}
	}
};

export default WorkLogQuery;<commit_msg>fix a bug: can't display the worklog with duration less than 8<commit_after>// Models
import WorkLog_TYPE from './WorkLogType.js';
import UserType from '../User/UserType.js';
// GraphQL
import {
	GraphQLString,
	GraphQLList,
	GraphQLInt,
	GraphQLFloat,
	GraphQLObjectType
} from 'graphql';
// RethinkDB
import r from 'rethinkdb';
// Constants
import { DB_HOST, DB_PORT, ADMIN_ID,TESTER_ID } from '../../constants/configurations.js';
import moment from 'moment';

let WorkLogQuery = {
	'getWorkLogList': {
		type: new GraphQLList(UserType),
		description: 'Get all worklog',
        args: {
			startDate: {
				type: GraphQLFloat,
				description: 'the start date of the query'
			},
			dateRange: {
				type: GraphQLInt,
				description: 'the date range of the query'
			}
		},
		resolve: async (root, { startDate , dateRange}) => {
			let connection = null,
			    result = [],
				query = null;

			try {
				if(dateRange <= 0){
					return result;
				}
				let endDate = startDate + (dateRange -1) * 1000 * 3600 * 24;
				query = r.db('work_genius').table('users').filter(r.row('id').ne(ADMIN_ID).and(r.row('id').ne(TESTER_ID)))
					.pluck('id','name','location').coerceTo('array');
				connection = await r.connect({ host: DB_HOST, port: DB_PORT });
				//get all users
				let users = await query.run(connection);

				//get all PTO data
				query = r.db('work_genius').table('pto')
					.filter(r.row('status').eq('PENDING').or(r.row('status').eq('APPROVED')))
					.filter(r.row('hours').coerceTo('number').ge(8))
					.pluck('applicant_id','start_date','end_date','hours').coerceTo('array');
				let ptoList = await query.run(connection);

				//get all uncompleted worklog list
				query = r.db('work_genius').table('worklog')
					.filter(r.js('(function(row){ \
						return (row.start_date >= '+startDate+' && row.start_date <= '+endDate+') \
							|| (row.start_date < '+startDate+' && row.end_date >= '+startDate+' )\
						})'))
					.coerceTo('array');
				let worklogList = await query.run(connection);

				//get all dates and check if the date is weekend or not
				let dateList = [];
				for(let i=0; i < dateRange; i++){
					let tmpDate  = startDate + i * 1000 * 3600 * 24;
					dateList.push({
						date: tmpDate,
						day_type: [0,6].includes(moment(tmpDate).day())? 'holiday':'workday'
					});
				}

				//get all public holiday
				query = r.db('work_genius').table('holiday')
					.filter(r.row('date').ge(startDate)).coerceTo('array');
				let holidayList = await query.run(connection);

				//construct the result array
				for(let user of users){
					let userItem = {...user,worklogs:[]};
					for(let dateItem of dateList){
						userItem.worklogs.push(Object.assign({},dateItem));
					}

					userItem.worklogs.forEach(dateItem => {
						//set pto info
						let findPTO = ptoList.find( pto => {
							if(moment(pto.start_date).isSame(moment(pto.end_date))){
								return pto.applicant_id == user.id
									&& moment(dateItem.date).isSame(moment(pto.start_date));
							}else{
								return pto.applicant_id == user.id
									&& (moment(dateItem.date).isBetween(pto.start_date,pto.end_date)
										|| moment(dateItem.date).isSame(pto.start_date,'day')
										|| moment(dateItem.date).isSame(pto.end_date,'day'));
							}
						});
						if(!!findPTO){
							dateItem.day_type = 'pto';
						}

						//set public holiday info
						let findHoliday = holidayList.find( holiday => {
							return holiday.date == dateItem.date && holiday.location == userItem.location;
						});
						if(!!findHoliday){
							dateItem.day_type = findHoliday.type;
						}
					});

					//get all my worklog list
					let myWorkLogList = worklogList.filter(log => {
						return log.employee_id === userItem.id;
					});

					//assign the worklog to the proper date
					if(myWorkLogList && myWorkLogList.length > 0){
						myWorkLogList.forEach(log => {
							let tmpStartDate = startDate > log.start_date ? startDate: log.start_date;
							let tmpEndDate = endDate > log.end_date ? log.end_date : endDate;
							for(let date = tmpStartDate ; date <= tmpEndDate; date += 1000 * 60 * 60 * 24){
								let dateItem = userItem.worklogs.find(dateItem => {
									return moment(dateItem.date).isSame(date,'day');
								})
								if(dateItem && dateItem.day_type == 'workday'){
									dateItem.worklog_items = dateItem.worklog_items || [];
									dateItem.worklog_items.push(log);
								}
							}
						});
					}

					result.push(userItem);
				}
				await connection.close();
				return result;
			} catch (err) {
				return err;
			}
			return result;
		}
	},
	'getWorkLogByEmployeeId': {
		type: new GraphQLList(UserType),
		description: 'Get all worklog of selected user',
        args: {
			startDate: {
				type: GraphQLFloat,
				description: 'the start date of the query'
			},
			dateRange: {
				type: GraphQLInt,
				description: 'the date range of the query'
			},
			employeeId: {
				type: GraphQLString,
				description: 'the employee id'
			}
		},
		resolve: async (root, { startDate , dateRange , employeeId}) => {
			let connection = null,
				query = null,
			    result = [];

			try {
				let endDate = startDate + (dateRange -1) * 1000 * 3600 * 24;
				query = r.db('work_genius').table('users').get(employeeId)
					.pluck('id','name','location');
				connection = await r.connect({ host: DB_HOST, port: DB_PORT });
				//get all users
				let user = await query.run(connection);

				//get all PTO data
				query = r.db('work_genius').table('pto')
					.filter({'applicant_id':employeeId})
					.filter(r.row('status').eq('PENDING').or(r.row('status').eq('APPROVED')))
					.filter(r.row('hours').coerceTo('number').ge(8))
					.pluck('applicant_id','start_date','end_date','hours').coerceTo('array');
				let ptoList = await query.run(connection);

				//get all uncompleted worklog list
				query = r.db('work_genius').table('worklog')
					.filter({employee_id:employeeId})
					.filter(r.js('(function(row){ \
						return (row.start_date >= '+startDate+' && row.start_date <= '+endDate+') \
							|| (row.start_date < '+startDate+' && row.end_date >= '+startDate+' )\
						})'))
					.coerceTo('array');
				let worklogList = await query.run(connection);

				//get all dates and check if the date is weekend or not
				let dateList = [];
				for(let i=0; i < dateRange; i++){
					let tmpDate  = startDate + i * 1000 * 3600 * 24;
					dateList.push({
						date: tmpDate,
						day_type: [0,6].includes(moment(tmpDate).day())? 'holiday':'workday'
					});
				}

				//get all public holiday
				query = r.db('work_genius').table('holiday')
					.filter({location:user.location})
					.filter(r.row('date').ge(startDate)).coerceTo('array');
				let holidayList = await query.run(connection);

				//construct the result array
				let userItem = {...user,worklogs:[]};
				for(let dateItem of dateList){
					userItem.worklogs.push(Object.assign({},dateItem));
				}

				userItem.worklogs.forEach(dateItem => {
					//set pto info
					let findPTO = ptoList.find( pto => {
						if(moment(pto.start_date).isSame(moment(pto.end_date))){
							return pto.applicant_id == user.id
								&& moment(dateItem.date).isSame(moment(pto.start_date));
						}else{
							return pto.applicant_id == user.id
								&& (moment(dateItem.date).isBetween(pto.start_date,pto.end_date)
									|| moment(dateItem.date).isSame(pto.start_date,'day')
									|| moment(dateItem.date).isSame(pto.end_date,'day'));
						}
					});
					if(!!findPTO){
						dateItem.day_type = 'pto';
					}

					//set public holiday info
					let findHoliday = holidayList.find( holiday => {
						return holiday.date == dateItem.date && holiday.location == userItem.location;
					});
					if(!!findHoliday){
						dateItem.day_type = findHoliday.type;
					}
				});

				//get all my worklog list
				let myWorkLogList = worklogList.filter(log => {
					return log.employee_id === userItem.id;
				});

				//assign the worklog to the proper date
				if(myWorkLogList && myWorkLogList.length > 0){
					myWorkLogList.forEach(log => {
						let tmpStartDate = startDate > log.start_date ? startDate: log.start_date;
						let tmpEndDate = endDate > log.end_date ? log.end_date : endDate;
						for(let date = tmpStartDate ; date <= tmpEndDate; date += 1000 * 60 * 60 * 24){
							let dateItem = userItem.worklogs.find(dateItem => {
								return moment(dateItem.date).isSame(date,'day');
							})
							if(dateItem && dateItem.day_type == 'workday'){
								dateItem.worklog_items = dateItem.worklog_items || [];
								dateItem.worklog_items.push(log);
							}
						}
					});
				}

				result.push(userItem);

				await connection.close();
				return result;
			} catch (err) {
				return err;
			}
			return result;
		}
	}
};

export default WorkLogQuery;<|endoftext|>


<commit_before>(function()
{
    "use strict";

    var math = require('mathjs');

    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    // additional functions beyond the traditional z^2 + c

    var applyFnMultC = function(fn, z, c)
    {
        var a = fn(z);
        var z2 = math.multiply(a, c);

        return this.finite(z2);
    };

    var applyFnMultZ = function(fn, z, zr, c)
    {
        var a = fn(zr);
        var z2 = math.chain(a).multiply(z).add(c).done();

        return this.finite(z2);

    };

    exports.processes = [
        {
            name: 'z2plusc',
            weight: 1,
            fn: function(z, c)
            {
                return math.chain(z)
                    .square()
                    .add(c)
                    .done();
            }
        },
        {
            name: 'znplusc',
            weight: 1,
            fn: function(z, c)
            {
                return math.chain(z)
                    .pow(this.pow)
                    .add(c)
                    .done();
            }
        },
        {
            name: 'zc',
            weight: 1,
            fn: function(z, c)
            {
                return math.multiply(z, c);
            }
        },
        {
            name: 'coszc',
            weight: 1,
            fn: function(z, c)
            {
                // convert to radians up to 2pi
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                // pass this (the functal object) as the context
                return applyFnMultC.call(this, math.cos, zr, c);
            }
        },
        {
            name: 'acoszc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.acos, z, c);
            }
        },
        {
            name: 'cotzc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.cot, z, c);
            }
        },
        // {
        //     name: 'cothzc',
        //     weight: 0.5,
        //     fn: function(z, c)
        //     {
        //         return applyFnMultC.call(this, math.coth, z, c);
        //     }
        // },
        // {
        //     name: 'csczc',
        //     weight: 0.01,
        //     fn: function(z, c)
        //     {
        //         return applyFnMultC.call(this, math.csc, z, c);
        //     }
        // },
        // {
        //     name: 'cschzc',
        //     weight: 0.01,
        //     fn: function(z, c)
        //     {
        //         return applyFnMultC.call(this, math.csch, z, c);
        //     }
        // },
        {
            name: 'expzc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.exp, z, c);
            }
        },
        {
            name: 'logzc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.log, z, c);
            }
        },
        {
            name: 'zsinz',
            weight: 1,
            fn: function(z, c)
            {
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                return applyFnMultZ.call(this, math.sin, z, zr, c);
            }
        },
        {
            name: 'z2sinz',
            weight: 0.5,
            fn: function(z, c)
            {
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                return applyFnMultZ.call(this, math.sin, math.multiply(z, z), zr, c);
            }
        },
        {
            name: 'z2plussinzplusc',
            weight: 1,
            fn: function(z, c)
            {
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));
                var szr = this.finite(math.sin(zr));

                return math.chain(z)
                    .pow(2)
                    .add(szr)
                    .add(c)
                    .done();
            }
        },

        {
            name: 'znplusxyplusc',
            weight: 1,
            fn: (function()
            {
                var znplusxyplusc = {
                    xfactor: math.random(5),
                    yfactor: math.random(5)
                };

                return function(z, c)
                {
                    if (!this.znplusxyplusc)
                    {
                        this.znplusxyplusc = znplusxyplusc;
                    }

                    return this.finite(math.chain(z)
                        .pow(this.pow)
                        .add(znplusxyplusc.xfactor * z.re)
                        .add(znplusxyplusc.yfactor * z.im)
                        .add(c)
                        .done());
                };
            })()
        },
        {
            // adjust real & imag parts with function of the opposite
            name: 'fxtrigy',
            weight: 0.05, // good, but too easily chosen, so reduce weight
            fn: (function()
            {
                // options will be the same for the entire run
                var trig = Rp.wandom([math.sin, math.cos]);

                // keep inside anon function so they are constant
                var fxtrigy = {
                    ampl1: math.random(0.2),
                    ampl2: math.random(0.2),
                    freq1: math.random(20),
                    freq2: math.random(20),
                    fn: trig,
                    name: Rp.nameOf(trig)
                };

                // the actual process function

                return function(z /*, c */ )
                {
                    // store options on first call
                    if (!this.fxtrigy)
                    {
                        this.fxtrigy = fxtrigy;
                    }

                    var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                    var fim = fxtrigy.ampl1 * fxtrigy.fn(fxtrigy.freq1 * zr.im);
                    var fre = fxtrigy.ampl2 * fxtrigy.fn(fxtrigy.freq2 * zr.re);

                    var z2 = math.complex(z.re - fim, z.im - fre);

                    return this.finite(z2);
                };
            })()
        },
        {
            // adjust real & imag parts with function of the opposite
            name: 'fxfny',
            weight: 0.05, // good, but too easily chosen, so reduce weight
            fn: (function()
            {
                var funcs = R.times(function()
                {
                    // todo: add ampl & freq to sin
                    return Rp.wandom([math.square, math.sin, R.compose(math.log, math.abs)]);
                }, 2);

                var fxfny = R.map(Rp.nameOf, funcs);

                // the actual process function

                return function(z /*, c */ )
                {
                    // store options on first call
                    if (!this.fxfny)
                    {
                        this.fxfny = fxfny;
                    }

                    var z2 = math.complex(this.finite(z.re + funcs[0](z.im)), this.finite(z.im + funcs[1](z.re)));

                    return this.finite(z2);
                };
            })()
        },
    ];

}());
<commit_msg>a bit more mess<commit_after>(function()
{
    "use strict";

    var math = require('mathjs');

    var R = require('ramda');
    var Rp = require('./plus-fp/plus-fp');

    // additional functions beyond the traditional z^2 + c

    var applyFnMultC = function(fn, z, c)
    {
        var a = fn(z);
        var z2 = math.multiply(a, c);

        return this.finite(z2);
    };

    var applyFnMultZ = function(fn, z, zr, c)
    {
        var a = fn(zr);
        var z2 = math.chain(a).multiply(z).add(c).done();

        return this.finite(z2);

    };

    exports.processes = [
        {
            name: 'z2plusc',
            weight: 1,
            fn: function(z, c)
            {
                return math.chain(z)
                    .square()
                    .add(c)
                    .done();
            }
        },
        {
            name: 'znplusc',
            weight: 1,
            fn: function(z, c)
            {
                return math.chain(z)
                    .pow(this.pow)
                    .add(c)
                    .done();
            }
        },
        {
            name: 'zc',
            weight: 1,
            fn: function(z, c)
            {
                return math.multiply(z, c);
            }
        },
        {
            name: 'coszc',
            weight: 1,
            fn: function(z, c)
            {
                // convert to radians up to 2pi
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                // pass this (the functal object) as the context
                return applyFnMultC.call(this, math.cos, zr, c);
            }
        },
        {
            name: 'acoszc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.acos, z, c);
            }
        },
        {
            name: 'cotzc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.cot, z, c);
            }
        },
        {
            name: 'cothzc',
            weight: 0.1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.coth, z, c);
            }
        },
        {
            name: 'csczc',
            weight: 0.1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.csc, z, c);
            }
        },
        {
            name: 'cschzc',
            weight: 0.1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.csch, z, c);
            }
        },
        {
            name: 'expzc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.exp, z, c);
            }
        },
        {
            name: 'logzc',
            weight: 1,
            fn: function(z, c)
            {
                return applyFnMultC.call(this, math.log, z, c);
            }
        },
        {
            name: 'zsinz',
            weight: 1,
            fn: function(z, c)
            {
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                return applyFnMultZ.call(this, math.sin, z, zr, c);
            }
        },
        {
            name: 'z2sinz',
            weight: 0.5,
            fn: function(z, c)
            {
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                return applyFnMultZ.call(this, math.sin, math.multiply(z, z), zr, c);
            }
        },
        {
            name: 'z2plussinzplusc',
            weight: 1,
            fn: function(z, c)
            {
                var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));
                var szr = this.finite(math.sin(zr));

                return math.chain(z)
                    .pow(2)
                    .add(szr)
                    .add(c)
                    .done();
            }
        },

        {
            name: 'znplusxyplusc',
            weight: 1,
            fn: (function()
            {
                var znplusxyplusc = {
                    xfactor: math.random(5),
                    yfactor: math.random(5)
                };

                return function(z, c)
                {
                    if (!this.znplusxyplusc)
                    {
                        this.znplusxyplusc = znplusxyplusc;
                    }

                    return this.finite(math.chain(z)
                        .pow(this.pow)
                        .add(znplusxyplusc.xfactor * z.re)
                        .add(znplusxyplusc.yfactor * z.im)
                        .add(c)
                        .done());
                };
            })()
        },
        {
            // adjust real & imag parts with function of the opposite
            name: 'fxtrigy',
            weight: 0.05, // good, but too easily chosen, so reduce weight
            fn: (function()
            {
                // options will be the same for the entire run
                var trig = Rp.wandom([math.sin, math.cos]);

                // keep inside anon function so they are constant
                var fxtrigy = {
                    ampl1: math.random(0.2),
                    ampl2: math.random(0.2),
                    freq1: math.random(20),
                    freq2: math.random(20),
                    fn: trig,
                    name: Rp.nameOf(trig)
                };

                // the actual process function

                return function(z /*, c */ )
                {
                    // store options on first call
                    if (!this.fxtrigy)
                    {
                        this.fxtrigy = fxtrigy;
                    }

                    var zr = math.complex(math.mod(z.re, math.pi * 2), math.mod(z.im, math.pi * 2));

                    var fim = fxtrigy.ampl1 * fxtrigy.fn(fxtrigy.freq1 * zr.im);
                    var fre = fxtrigy.ampl2 * fxtrigy.fn(fxtrigy.freq2 * zr.re);

                    var z2 = math.complex(z.re - fim, z.im - fre);

                    return this.finite(z2);
                };
            })()
        },
        {
            // adjust real & imag parts with function of the opposite
            name: 'fxfny',
            weight: 0.05, // good, but too easily chosen, so reduce weight
            fn: (function()
            {
                var funcs = R.times(function()
                {
                    // todo: add ampl & freq to sin
                    return Rp.wandom([math.square, math.sin, R.compose(math.log, math.abs)]);
                }, 2);

                var fxfny = R.map(Rp.nameOf, funcs);

                // the actual process function

                return function(z /*, c */ )
                {
                    // store options on first call
                    if (!this.fxfny)
                    {
                        this.fxfny = fxfny;
                    }

                    var z2 = math.complex(this.finite(z.re + funcs[0](z.im)), this.finite(z.im + funcs[1](z.re)));

                    return this.finite(z2);
                };
            })()
        },
    ];

}());
<|endoftext|>


<commit_before>const test = require('ava');
const {spawn} = require('child_process');
const WebSocket = require('ws');
const WebSocketServer = require('ws').Server;
const ReconnectingWebSocket = require('..');

const PORT = 50123;
const PORT_UNRESPONSIVE = 50124;
const URL = `ws://localhost:${PORT}`;

test.beforeEach(() => {
    global.WebSocket = WebSocket;
});

test.afterEach(() => {
    delete global.WebSocket;
});

test('throws with invalid constructor', t => {
    delete global.WebSocket;
    t.throws(() => {
        new ReconnectingWebSocket(URL, undefined, {WebSocket: 123});
    });
});

test('throws with missing constructor', t => {
    delete global.WebSocket;
    t.throws(() => {
        new ReconnectingWebSocket(URL, undefined);
    });
});

test('throws if not created with `new`', t => {
    t.throws(() => {
        ReconnectingWebSocket(URL, undefined);
    }, TypeError);
});

test.cb('global WebSocket is used if available', t => {
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    ws.onerror = () => {
        t.true(ws._ws instanceof WebSocket);
        t.end();
    };
});

test.cb('send is ignored when not ready', t => {
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    ws.send('message');
    ws.onerror = () => {
        t.pass();
        t.end();
    };
});

test.cb('getters when not ready', t => {
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    t.is(ws.bufferedAmount, 0);
    t.is(ws.protocol, '');
    t.is(ws.url, '');
    t.is(ws.extensions, '');
    t.is(ws.binaryType, 'blob');

    ws.onerror = () => {
        t.pass();
        t.end();
    };
});

test.cb('debug', t => {
    const log = console.log;
    console.log = () => t.pass();

    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
        debug: true,
    });

    ws.onerror = () => {
        ws._options.debug = false;
        console.log = log;
        t.end();
    };
});

test.cb('pass WebSocket via options', t => {
    delete global.WebSocket;
    const ws = new ReconnectingWebSocket(URL, undefined, {
        WebSocket,
        maxRetries: 0,
    });
    ws.onerror = () => {
        t.true(ws._ws instanceof WebSocket);
        t.end();
    };
});

test('URL provider', async t => {
    const url = 'example.com';
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    t.is(await ws._getNextUrl(url), url, 'string');
    t.is(await ws._getNextUrl(() => url), url, '() -> string');
    t.is(await ws._getNextUrl(() => Promise.resolve(url)), url, '() -> Promise<string>');

    try {
        await ws._getNextUrl(123);
        t.fail();
    } catch (e) {
        t.pass();
    }

    try {
        await ws._getNextUrl(() => 123);
        t.fail();
    } catch (e) {
        t.pass();
    }
});

test('connection status constants', t => {
    const ws = new ReconnectingWebSocket(URL, null, {maxRetries: 0});

    t.is(ReconnectingWebSocket.CONNECTING, 0);
    t.is(ReconnectingWebSocket.OPEN, 1);
    t.is(ReconnectingWebSocket.CLOSING, 2);
    t.is(ReconnectingWebSocket.CLOSED, 3);

    t.is(ws.CONNECTING, 0);
    t.is(ws.OPEN, 1);
    t.is(ws.CLOSING, 2);
    t.is(ws.CLOSED, 3);
    ws.close();
});

const maxRetriesTest = (count, t) => {
    const ws = new ReconnectingWebSocket(URL, null, {
        maxRetries: count,
        maxReconnectionDelay: 200,
    });
    t.plan(count + 1);

    ws.addEventListener('error', event => {
        t.pass();
        if (ws.retryCount === count) {
            setTimeout(() => t.end(), 500);
        }
        if (ws.retryCount > count) {
            t.fail(`too many retries: ${ws.retryCount}`);
        }
    });
};

test.cb('max retries: 0', t => maxRetriesTest(0, t));
test.cb('max retries: 1', t => maxRetriesTest(1, t));
test.cb('max retries: 5', t => maxRetriesTest(5, t));

test.cb('level0 event listeners are kept after reconnect', t => {
    const ws = new ReconnectingWebSocket(URL, null, {
        maxRetries: 4,
        reconnectionDelayFactor: 1.2,
        maxReconnectionDelay: 20,
        minReconnectionDelay: 10,
    });

    const handleOpen = () => {};
    const handleClose = () => {};
    const handleMessage = () => {};
    const handleError = () => {
        t.is(ws.onopen, handleOpen);
        t.is(ws.onclose, handleClose);
        t.is(ws.onmessage, handleMessage);
        t.is(ws.onerror, handleError);
        if (ws.retryCount === 4) {
            t.end();
        }
    };

    ws.onopen = handleOpen;
    ws.onclose = handleClose;
    ws.onmessage = handleMessage;
    ws.onerror = handleError;
});

test.cb('level2 event listeners', t => {
    const anyProtocol = 'foobar';
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, anyProtocol, {});

    ws.addEventListener('open', () => {
        t.is(ws.protocol, anyProtocol);
        t.is(ws.extensions, '');
        t.is(ws.bufferedAmount, 0);
        ws.close();
    });

    const fail = () => {
        t.fail();
    };
    ws.addEventListener('unknown1', fail);
    ws.addEventListener('open', fail);
    ws.addEventListener('open', fail);
    ws.removeEventListener('open', fail);
    ws.removeEventListener('unknown2', fail);

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('connection timeout', t => {
    const proc = spawn('node', [`${__dirname}/unresponsive-server.js`, PORT_UNRESPONSIVE, 5000]);
    t.plan(2);

    let lock = false;
    proc.stdout.on('data', d => {
        if (lock) return;
        lock = true;

        const ws = new ReconnectingWebSocket(`ws://localhost:${PORT_UNRESPONSIVE}`, null, {
            minReconnectionDelay: 50,
            connectionTimeout: 500,
            maxRetries: 1,
        });

        ws.addEventListener('error', event => {
            t.is(event.message, 'TIMEOUT');
            if (ws.retryCount === 1) {
                setTimeout(() => t.end(), 1000);
            }
        });

        ws.addEventListener('close', event => {
            console.log('>>>> CLOSE', event.message);
        });
    });
});

test.cb('getters', t => {
    const anyProtocol = 'foobar';
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, anyProtocol, {maxReconnectionDelay: 100});

    ws.addEventListener('open', () => {
        t.is(ws.protocol, anyProtocol);
        t.is(ws.extensions, '');
        t.is(ws.bufferedAmount, 0);
        t.is(ws.binaryType, 'nodebuffer');
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('binaryType', t => {
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, undefined, {minReconnectionDelay: 0});

    t.is(ws.binaryType, 'blob');
    ws.binaryType = 'arraybuffer';
    ws.addEventListener('open', () => {
        t.is(ws.binaryType, 'arraybuffer', 'assigned after open');
        ws.binaryType = 'nodebuffer';
        t.is(ws.binaryType, 'nodebuffer');
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('calling to close multiple times', t => {
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, undefined, {});

    ws.addEventListener('open', () => {
        ws.close();
        ws.close();
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('calling to reconnect when not ready', t => {
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, undefined, {});
    ws.reconnect();
    ws.reconnect();

    ws.addEventListener('open', () => {
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('connect, send, receive, close', t => {
    const anyMessageText = 'hello';
    const anyProtocol = 'foobar';

    const wss = new WebSocketServer({port: PORT});
    wss.on('connection', ws => {
        ws.on('message', msg => {
            ws.send(msg);
        });
    });
    wss.on('error', () => {
        t.fail();
    });

    t.plan(7);

    const ws = new ReconnectingWebSocket(URL, anyProtocol, {
        minReconnectionDelay: 100,
        maxReconnectionDelay: 200,
    });
    t.is(ws.readyState, ws.CONNECTING);

    ws.addEventListener('open', () => {
        t.is(ws.protocol, anyProtocol);
        t.is(ws.readyState, ws.OPEN);
        ws.send(anyMessageText);
    });

    ws.addEventListener('message', msg => {
        t.is(msg.data, anyMessageText);
        ws.close(1000, '');
        t.is(ws.readyState, ws.CLOSING);
    });

    ws.addEventListener('close', () => {
        t.is(ws.readyState, ws.CLOSED);
        t.is(ws.url, URL);
        wss.close();
        setTimeout(() => t.end(), 1000);
    });
});

test.cb('connect, send, receive, reconnect', t => {
    const anyMessageText = 'hello';
    const anyProtocol = 'foobar';

    const wss = new WebSocketServer({port: PORT});
    wss.on('connection', ws => {
        ws.on('message', msg => {
            ws.send(msg);
        });
    });

    const totalRounds = 3;
    let currentRound = 0;

    // 6 = 3 * 2 open
    // 8 = 2 * 3 message + 2 reconnect
    // 7 = 2 * 3 close + 1 closed
    t.plan(21);

    const ws = new ReconnectingWebSocket(URL, anyProtocol, {
        minReconnectionDelay: 100,
        maxReconnectionDelay: 200,
    });

    ws.onopen = () => {
        currentRound++;
        t.is(ws.protocol, anyProtocol);
        t.is(ws.readyState, ws.OPEN);
        ws.send(anyMessageText);
    };

    ws.onmessage = msg => {
        t.is(msg.data, anyMessageText);
        if (currentRound < totalRounds) {
            ws.reconnect(1000, 'reconnect');
            t.is(ws.retryCount, 0);
        } else {
            ws.close(1000, 'close');
        }
        t.is(ws.readyState, ws.CLOSING);
    };

    ws.addEventListener('close', event => {
        t.is(ws.url, URL);
        if (currentRound >= totalRounds) {
            t.is(ws.readyState, ws.CLOSED);
            wss.close();
            setTimeout(() => t.end(), 1000);
            t.is(event.reason, 'close');
        } else {
            t.is(event.reason, 'reconnect');
        }
    });
});

test.cb('immediatly-failed connection should not timeout', t => {
    const ws = new ReconnectingWebSocket('ws://thiswillfail.com', null, {
        maxRetries: 2,
        connectionTimeout: 500,
        debug: 1,
    });

    ws.addEventListener('error', err => {
        if (err.message === 'TIMEOUT') {
            t.fail();
        }
        if (ws.retryCount === 2) {
            setTimeout(() => t.end(), 500);
        }
        if (ws.retryCount > 2) {
            t.fail();
        }
    });
});
<commit_msg>remove debug code<commit_after>const test = require('ava');
const {spawn} = require('child_process');
const WebSocket = require('ws');
const WebSocketServer = require('ws').Server;
const ReconnectingWebSocket = require('..');

const PORT = 50123;
const PORT_UNRESPONSIVE = 50124;
const URL = `ws://localhost:${PORT}`;

test.beforeEach(() => {
    global.WebSocket = WebSocket;
});

test.afterEach(() => {
    delete global.WebSocket;
});

test('throws with invalid constructor', t => {
    delete global.WebSocket;
    t.throws(() => {
        new ReconnectingWebSocket(URL, undefined, {WebSocket: 123});
    });
});

test('throws with missing constructor', t => {
    delete global.WebSocket;
    t.throws(() => {
        new ReconnectingWebSocket(URL, undefined);
    });
});

test('throws if not created with `new`', t => {
    t.throws(() => {
        ReconnectingWebSocket(URL, undefined);
    }, TypeError);
});

test.cb('global WebSocket is used if available', t => {
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    ws.onerror = () => {
        t.true(ws._ws instanceof WebSocket);
        t.end();
    };
});

test.cb('send is ignored when not ready', t => {
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    ws.send('message');
    ws.onerror = () => {
        t.pass();
        t.end();
    };
});

test.cb('getters when not ready', t => {
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    t.is(ws.bufferedAmount, 0);
    t.is(ws.protocol, '');
    t.is(ws.url, '');
    t.is(ws.extensions, '');
    t.is(ws.binaryType, 'blob');

    ws.onerror = () => {
        t.pass();
        t.end();
    };
});

test.cb('debug', t => {
    const log = console.log;
    console.log = () => t.pass();

    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
        debug: true,
    });

    ws.onerror = () => {
        ws._options.debug = false;
        console.log = log;
        t.end();
    };
});

test.cb('pass WebSocket via options', t => {
    delete global.WebSocket;
    const ws = new ReconnectingWebSocket(URL, undefined, {
        WebSocket,
        maxRetries: 0,
    });
    ws.onerror = () => {
        t.true(ws._ws instanceof WebSocket);
        t.end();
    };
});

test('URL provider', async t => {
    const url = 'example.com';
    const ws = new ReconnectingWebSocket(URL, undefined, {
        maxRetries: 0,
    });
    t.is(await ws._getNextUrl(url), url, 'string');
    t.is(await ws._getNextUrl(() => url), url, '() -> string');
    t.is(await ws._getNextUrl(() => Promise.resolve(url)), url, '() -> Promise<string>');

    try {
        await ws._getNextUrl(123);
        t.fail();
    } catch (e) {
        t.pass();
    }

    try {
        await ws._getNextUrl(() => 123);
        t.fail();
    } catch (e) {
        t.pass();
    }
});

test('connection status constants', t => {
    const ws = new ReconnectingWebSocket(URL, null, {maxRetries: 0});

    t.is(ReconnectingWebSocket.CONNECTING, 0);
    t.is(ReconnectingWebSocket.OPEN, 1);
    t.is(ReconnectingWebSocket.CLOSING, 2);
    t.is(ReconnectingWebSocket.CLOSED, 3);

    t.is(ws.CONNECTING, 0);
    t.is(ws.OPEN, 1);
    t.is(ws.CLOSING, 2);
    t.is(ws.CLOSED, 3);
    ws.close();
});

const maxRetriesTest = (count, t) => {
    const ws = new ReconnectingWebSocket(URL, null, {
        maxRetries: count,
        maxReconnectionDelay: 200,
    });
    t.plan(count + 1);

    ws.addEventListener('error', event => {
        t.pass();
        if (ws.retryCount === count) {
            setTimeout(() => t.end(), 500);
        }
        if (ws.retryCount > count) {
            t.fail(`too many retries: ${ws.retryCount}`);
        }
    });
};

test.cb('max retries: 0', t => maxRetriesTest(0, t));
test.cb('max retries: 1', t => maxRetriesTest(1, t));
test.cb('max retries: 5', t => maxRetriesTest(5, t));

test.cb('level0 event listeners are kept after reconnect', t => {
    const ws = new ReconnectingWebSocket(URL, null, {
        maxRetries: 4,
        reconnectionDelayFactor: 1.2,
        maxReconnectionDelay: 20,
        minReconnectionDelay: 10,
    });

    const handleOpen = () => {};
    const handleClose = () => {};
    const handleMessage = () => {};
    const handleError = () => {
        t.is(ws.onopen, handleOpen);
        t.is(ws.onclose, handleClose);
        t.is(ws.onmessage, handleMessage);
        t.is(ws.onerror, handleError);
        if (ws.retryCount === 4) {
            t.end();
        }
    };

    ws.onopen = handleOpen;
    ws.onclose = handleClose;
    ws.onmessage = handleMessage;
    ws.onerror = handleError;
});

test.cb('level2 event listeners', t => {
    const anyProtocol = 'foobar';
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, anyProtocol, {});

    ws.addEventListener('open', () => {
        t.is(ws.protocol, anyProtocol);
        t.is(ws.extensions, '');
        t.is(ws.bufferedAmount, 0);
        ws.close();
    });

    const fail = () => {
        t.fail();
    };
    ws.addEventListener('unknown1', fail);
    ws.addEventListener('open', fail);
    ws.addEventListener('open', fail);
    ws.removeEventListener('open', fail);
    ws.removeEventListener('unknown2', fail);

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('connection timeout', t => {
    const proc = spawn('node', [`${__dirname}/unresponsive-server.js`, PORT_UNRESPONSIVE, 5000]);
    t.plan(2);

    let lock = false;
    proc.stdout.on('data', d => {
        if (lock) return;
        lock = true;

        const ws = new ReconnectingWebSocket(`ws://localhost:${PORT_UNRESPONSIVE}`, null, {
            minReconnectionDelay: 50,
            connectionTimeout: 500,
            maxRetries: 1,
        });

        ws.addEventListener('error', event => {
            t.is(event.message, 'TIMEOUT');
            if (ws.retryCount === 1) {
                setTimeout(() => t.end(), 1000);
            }
        });

        ws.addEventListener('close', event => {
            console.log('>>>> CLOSE', event.message);
        });
    });
});

test.cb('getters', t => {
    const anyProtocol = 'foobar';
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, anyProtocol, {maxReconnectionDelay: 100});

    ws.addEventListener('open', () => {
        t.is(ws.protocol, anyProtocol);
        t.is(ws.extensions, '');
        t.is(ws.bufferedAmount, 0);
        t.is(ws.binaryType, 'nodebuffer');
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('binaryType', t => {
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, undefined, {minReconnectionDelay: 0});

    t.is(ws.binaryType, 'blob');
    ws.binaryType = 'arraybuffer';
    ws.addEventListener('open', () => {
        t.is(ws.binaryType, 'arraybuffer', 'assigned after open');
        ws.binaryType = 'nodebuffer';
        t.is(ws.binaryType, 'nodebuffer');
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('calling to close multiple times', t => {
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, undefined, {});

    ws.addEventListener('open', () => {
        ws.close();
        ws.close();
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('calling to reconnect when not ready', t => {
    const wss = new WebSocketServer({port: PORT});
    const ws = new ReconnectingWebSocket(URL, undefined, {});
    ws.reconnect();
    ws.reconnect();

    ws.addEventListener('open', () => {
        ws.close();
    });

    ws.addEventListener('close', () => {
        wss.close();
        setTimeout(() => t.end(), 500);
    });
});

test.cb('connect, send, receive, close', t => {
    const anyMessageText = 'hello';
    const anyProtocol = 'foobar';

    const wss = new WebSocketServer({port: PORT});
    wss.on('connection', ws => {
        ws.on('message', msg => {
            ws.send(msg);
        });
    });
    wss.on('error', () => {
        t.fail();
    });

    t.plan(7);

    const ws = new ReconnectingWebSocket(URL, anyProtocol, {
        minReconnectionDelay: 100,
        maxReconnectionDelay: 200,
    });
    t.is(ws.readyState, ws.CONNECTING);

    ws.addEventListener('open', () => {
        t.is(ws.protocol, anyProtocol);
        t.is(ws.readyState, ws.OPEN);
        ws.send(anyMessageText);
    });

    ws.addEventListener('message', msg => {
        t.is(msg.data, anyMessageText);
        ws.close(1000, '');
        t.is(ws.readyState, ws.CLOSING);
    });

    ws.addEventListener('close', () => {
        t.is(ws.readyState, ws.CLOSED);
        t.is(ws.url, URL);
        wss.close();
        setTimeout(() => t.end(), 1000);
    });
});

test.cb('connect, send, receive, reconnect', t => {
    const anyMessageText = 'hello';
    const anyProtocol = 'foobar';

    const wss = new WebSocketServer({port: PORT});
    wss.on('connection', ws => {
        ws.on('message', msg => {
            ws.send(msg);
        });
    });

    const totalRounds = 3;
    let currentRound = 0;

    // 6 = 3 * 2 open
    // 8 = 2 * 3 message + 2 reconnect
    // 7 = 2 * 3 close + 1 closed
    t.plan(21);

    const ws = new ReconnectingWebSocket(URL, anyProtocol, {
        minReconnectionDelay: 100,
        maxReconnectionDelay: 200,
    });

    ws.onopen = () => {
        currentRound++;
        t.is(ws.protocol, anyProtocol);
        t.is(ws.readyState, ws.OPEN);
        ws.send(anyMessageText);
    };

    ws.onmessage = msg => {
        t.is(msg.data, anyMessageText);
        if (currentRound < totalRounds) {
            ws.reconnect(1000, 'reconnect');
            t.is(ws.retryCount, 0);
        } else {
            ws.close(1000, 'close');
        }
        t.is(ws.readyState, ws.CLOSING);
    };

    ws.addEventListener('close', event => {
        t.is(ws.url, URL);
        if (currentRound >= totalRounds) {
            t.is(ws.readyState, ws.CLOSED);
            wss.close();
            setTimeout(() => t.end(), 1000);
            t.is(event.reason, 'close');
        } else {
            t.is(event.reason, 'reconnect');
        }
    });
});

test.cb('immediatly-failed connection should not timeout', t => {
    const ws = new ReconnectingWebSocket('ws://thiswillfail.com', null, {
        maxRetries: 2,
        connectionTimeout: 500,
    });

    ws.addEventListener('error', err => {
        if (err.message === 'TIMEOUT') {
            t.fail();
        }
        if (ws.retryCount === 2) {
            setTimeout(() => t.end(), 500);
        }
        if (ws.retryCount > 2) {
            t.fail();
        }
    });
});
<|endoftext|>


<commit_before>var Fleet = require("../../models/Fleet.js");
var PlanetHelper = require("./planet_helper.js");

module.exports = function FleetHelper(fb_root)
{
	var helper = this;
    this.fb_root = fb_root;

    this.get_fleet_by_id = function(req,res){
        var name = req.query.name;

        if (name == undefined || name == "" || !/[0-9a-zA-Z]/.test(name)){
            res.json({success:false,message:"Invalid fleet name."});
            return;
        }

        fb_root.child("names").child(name).once("value",function(snap){
            if (!snap || !snap.val()){
                res.json({success:false,message:"Fleet named "+name+" does not exist."})
                return;
            }

            fb_root.child("fleets").child(snap.val()).once("value",function(snapshot){

                res.json({success:true,data:snapshot.val()});
            });

        });

    }

    this.get_fleet = function(req,res){
        var id = req.params.id;

        if (id == undefined || id == ""){
            res.json({success:false,message:"Must provide a valid id."});
        }

        fb_root.child("fleets").child(id).once("value",function(snap){
            if (!snap || !snap.val()){
                res.json({success:false,message:"Fleet with id "+id+" does not exist."});
                return;
            }

            res.json({success:true,data:snap.val()});
        });
    }

    this.add_resource = function(req,res){
        var id = req.params.id;
        var type = req.query.type;
        var amount = parseInt(req.query.amount);

        var planetHelper = new PlanetHelper(fb_root);

        if (!id || id == ""){
            res.json({success:false,message:"Must provide id."});
            return;
        }

        if (!type || !planetHelper.res_data[type]){
            res.json({success:false,message:"type must be "+Object.keys(planetHelper.res_data).join(",")});
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            fleet.data.resources[type] += amount;
            fleet.set("resources",fleet.data.resources);

            res.json({success:true,data:fleet.data});
        });
    }

    this.new_fleet = function(req,res){
        var name = req.query.name;

        if (name == undefined || name == "" || !/[0-9a-zA-Z]/.test(name)){
            res.json({success:false,message:"Creating a fleet requires a name that is alphanumeric and _."});
            return;
        }

        var planetHelper = new PlanetHelper(fb_root);
        planetHelper.makePlanet(name+"'s home world",0,false,function(planet){
            var planetId = planet.id;
           fb_root.child("names").child(name).once("value",function(snap){

                if(snap.val() != null){
                    res.json({success:false,message:"Name "+name+" already exists."});
                    return;
                }

                var refId = fb_root.child("fleets").push().key();

                var fleet = {
                    "id" : refId,
                    "current_planet":planetId,
                    "fuel" : 0,
                    "ships": [Fleet.makeShip("basic")],
                    "search_bonus":0,
                    "tech_level":0,
                    "colonies": [],
                    "resources":{
                        "copper":0,
                        "steel":0,
                        "aluminium":0,
                        "oil":0,
                        "coal":0,
                        "uranium":0,
                        "water":0,
                        "protein":0,
                        "dna":0,
                        "rare":0
                    },
                    "name":name
                };

                fb_root.child("names").child(name).set(refId);
                fb_root.child("fleets").child(refId).set(fleet);

                res.json({success:true,message:"success",data:fleet});
            });
        });
    }

    this.add_ship = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide fleet id."});
            return;
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            var ships = fleet.get("ships") || [];
            ships.push(Fleet.makeShip("basic"));
            fleet.set("ships",ships);

            res.json({success:true,data:fleet.data});

        });
    }

    this.update_fleet = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            fleet.update(fleet.data);
            res.json({success:true,data:fleet.data});
        })
    }

    this.upgrade = function(req,res){

    }

    this.upgrade_ship = function(req,res){

    }

    this.get_ship = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        if (!req.params.position){
            res.json({success:false,message:"Must provide a ship position."});
            return;
        }

        var position = parseInt(req.params.position);

        var fleet = new Fleet(fb_root,id,function(fleet){
            if (position < 0 || position >= fleet.data.ships.length){
                res.json({success:false,message:"Invalid position. You don't have that many ships."});
                return;
            }

            res.json({success:true,data:fleet.data.ships[position]});
        });
    }

    this.get_ships = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            res.json({success:true,data:fleet.data.ships});
            return;
        });
    }

    this.add_harvester = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        if (!req.params.position){
            res.json({success:false,message:"Must provide a ship position."});
            return;
        }

        var position = parseInt(req.params.position);

        var fleet = new Fleet(fb_root,id,function(fleet){
            if (position < 0 || position >= fleet.data.ships.length){
                res.json({success:false,message:"Invalid position. You don't have that many ships."});
                return;
            }

            var ship = fleet.data.ships[position];

            ship.harvesters.push(Fleet.makeHarvester());
            fleet.set("ships",fleet.data.ships);

            res.json({success:true,data:fleet.data});
        });
    }

}<commit_msg>add_harvester works<commit_after>var Fleet = require("../../models/Fleet.js");
var PlanetHelper = require("./planet_helper.js");

module.exports = function FleetHelper(fb_root)
{
	var helper = this;
    this.fb_root = fb_root;

    this.get_fleet_by_id = function(req,res){
        var name = req.query.name;

        if (name == undefined || name == "" || !/[0-9a-zA-Z]/.test(name)){
            res.json({success:false,message:"Invalid fleet name."});
            return;
        }

        fb_root.child("names").child(name).once("value",function(snap){
            if (!snap || !snap.val()){
                res.json({success:false,message:"Fleet named "+name+" does not exist."})
                return;
            }

            fb_root.child("fleets").child(snap.val()).once("value",function(snapshot){

                res.json({success:true,data:snapshot.val()});
            });

        });

    }

    this.get_fleet = function(req,res){
        var id = req.params.id;

        if (id == undefined || id == ""){
            res.json({success:false,message:"Must provide a valid id."});
        }

        fb_root.child("fleets").child(id).once("value",function(snap){
            if (!snap || !snap.val()){
                res.json({success:false,message:"Fleet with id "+id+" does not exist."});
                return;
            }

            res.json({success:true,data:snap.val()});
        });
    }

    this.add_resource = function(req,res){
        var id = req.params.id;
        var type = req.query.type;
        var amount = parseInt(req.query.amount);

        var planetHelper = new PlanetHelper(fb_root);

        if (!id || id == ""){
            res.json({success:false,message:"Must provide id."});
            return;
        }

        if (!type || !planetHelper.res_data[type]){
            res.json({success:false,message:"type must be "+Object.keys(planetHelper.res_data).join(",")});
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            fleet.data.resources[type] += amount;
            fleet.set("resources",fleet.data.resources);

            res.json({success:true,data:fleet.data});
        });
    }

    this.new_fleet = function(req,res){
        var name = req.query.name;

        if (name == undefined || name == "" || !/[0-9a-zA-Z]/.test(name)){
            res.json({success:false,message:"Creating a fleet requires a name that is alphanumeric and _."});
            return;
        }

        var planetHelper = new PlanetHelper(fb_root);
        planetHelper.makePlanet(name+"'s home world",0,false,function(planet){
            var planetId = planet.id;
           fb_root.child("names").child(name).once("value",function(snap){

                if(snap.val() != null){
                    res.json({success:false,message:"Name "+name+" already exists."});
                    return;
                }

                var refId = fb_root.child("fleets").push().key();

                var fleet = {
                    "id" : refId,
                    "current_planet":planetId,
                    "fuel" : 0,
                    "ships": [Fleet.makeShip("basic")],
                    "search_bonus":0,
                    "tech_level":0,
                    "colonies": [],
                    "resources":{
                        "copper":0,
                        "steel":0,
                        "aluminium":0,
                        "oil":0,
                        "coal":0,
                        "uranium":0,
                        "water":0,
                        "protein":0,
                        "dna":0,
                        "rare":0
                    },
                    "name":name
                };

                fb_root.child("names").child(name).set(refId);
                fb_root.child("fleets").child(refId).set(fleet);

                res.json({success:true,message:"success",data:fleet});
            });
        });
    }

    this.add_ship = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide fleet id."});
            return;
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            var ships = fleet.get("ships") || [];
            ships.push(Fleet.makeShip("basic"));
            fleet.set("ships",ships);

            res.json({success:true,data:fleet.data});

        });
    }

    this.update_fleet = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            fleet.update(fleet.data);
            res.json({success:true,data:fleet.data});
        })
    }

    this.upgrade = function(req,res){

    }

    this.upgrade_ship = function(req,res){

    }

    this.get_ship = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        if (!req.params.position){
            res.json({success:false,message:"Must provide a ship position."});
            return;
        }

        var position = parseInt(req.params.position);

        var fleet = new Fleet(fb_root,id,function(fleet){
            if (position < 0 || position >= fleet.data.ships.length){
                res.json({success:false,message:"Invalid position. You don't have that many ships."});
                return;
            }

            res.json({success:true,data:fleet.data.ships[position]});
        });
    }

    this.get_ships = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        var fleet = new Fleet(fb_root,id,function(fleet){
            res.json({success:true,data:fleet.data.ships});
            return;
        });
    }

    this.add_harvester = function(req,res){
        var id = req.params.id;

        if (!id){
            res.json({success:false,message:"Must provide a fleet id."});
            return;
        }

        if (!req.params.position){
            res.json({success:false,message:"Must provide a ship position."});
            return;
        }

        var position = parseInt(req.params.position);

        var fleet = new Fleet(fb_root,id,function(fleet){
            if (position < 0 || position >= fleet.data.ships.length){
                res.json({success:false,message:"Invalid position. You don't have that many ships."});
                return;
            }

            var ship = fleet.data.ships[position];
            if (!ship.harvesters){
                ship.harvesters = [];
            }

            ship.harvesters.push(Fleet.makeHarvester());
            fleet.set("ships",fleet.data.ships);

            res.json({success:true,data:fleet.data});
        });
    }

}<|endoftext|>


<commit_before>(function() {
  var DEFAULT_BUTTONS = [
    ['C', ' ', ' ', ' '],
    ['7', '8', '9', '/'],
    ['4', '5', '6', '*'],
    ['1', '2', '3', '-'],
    ['.', '0', '=', '+'],
  ];

  var Calculator = Ractive.extend({
    template: '#calculator_template',

    click: function(x, y) {
      var button = this.get('buttons')[y][x];
      if (this.special_buttons[button]) {
        this.special_buttons[button].bind(this)();
      } else {
        this.set('result', this.get('result') + button);
      }
    },

    submit: function(event) {
      event.original.preventDefault();
      this.calculate();
    },

    calculate: function() {
      this.set('result', eval(this.get('result')));
    },

    special_buttons: {
      ' ': function() {
      },
      'C': function() {
        this.set('result', '');
      },
      '=': function() {
        this.calculate();
      },
    }
  });

  new Calculator({
    el: '#calculator_app',
    data: {
      result: '',
      buttons: DEFAULT_BUTTONS,
    },
  });
})();
<commit_msg>Support back-space key<commit_after>(function() {
  var DEFAULT_BUTTONS = [
    ['C', ' ', ' ', '←'],
    ['7', '8', '9', '/'],
    ['4', '5', '6', '*'],
    ['1', '2', '3', '-'],
    ['.', '0', '=', '+'],
  ];

  var Calculator = Ractive.extend({
    template: '#calculator_template',

    click: function(x, y) {
      var button = this.get('buttons')[y][x];
      if (this.special_buttons[button]) {
        this.special_buttons[button].bind(this)();
      } else {
        this.set('result', this.get('result') + button);
      }
    },

    submit: function(event) {
      event.original.preventDefault();
      this.calculate();
    },

    calculate: function() {
      this.set('result', eval(this.get('result')));
    },

    special_buttons: {
      ' ': function() {
      },
      'C': function() {
        this.set('result', '');
      },
      '←': function() {
        var result = this.get('result');
        result = result.substr(0, result.length - 1);
        this.set('result', result);
      },
      '=': function() {
        this.calculate();
      },
    }
  });

  new Calculator({
    el: '#calculator_app',
    data: {
      result: '',
      buttons: DEFAULT_BUTTONS,
    },
  });
})();
<|endoftext|>


<commit_before>/**
 * EventEmitter tests
 */

(function() {
	test('Adding and retrieving listeners', function() {
		var ee = new EventEmitter();

		equal(ee.listeners('testEvent'), false, 'Checking for any listeners');

		ee.addListener('testEvent', function() {
			// Listener
		});

		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', function() {
			// Another listener for the same event
		});

		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.addListener('anotherTestEvent', function() {
			// Listener for new event
		});

		equal(ee.listeners('anotherTestEvent')[0].type, 'anotherTestEvent', 'Retrieving the first listener for a different event');

		ee.addListener('onTest', function() {
			// Listener via the alias
		});

		equal(ee.listeners('onTest')[0].type, 'onTest', 'Retrieving the first listener for a different event added via the on alias');
	});
}());<commit_msg>Added the second test<commit_after>/**
 * EventEmitter tests
 */

(function() {
	test('Adding and retrieving listeners', function() {
		var ee = new EventEmitter();

		equal(ee.listeners('testEvent'), false, 'Checking for any listeners');

		ee.addListener('testEvent', function() {
			// Listener
		});
		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', function() {
			// Another listener for the same event
		});
		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.addListener('anotherTestEvent', function() {
			// Listener for new event
		});
		equal(ee.listeners('anotherTestEvent')[0].type, 'anotherTestEvent', 'Retrieving the first listener for a different event');

		ee.addListener('anotherTestEvent', function() {
			// Another listener for new event
		});
		equal(ee.listeners('anotherTestEvent')[1].type, 'anotherTestEvent', 'Retrieving the second listener for a different event');

		ee.addListener('onTest', function() {
			// Listener via the alias
		});
		equal(ee.listeners('onTest')[0].type, 'onTest', 'Retrieving the first listener for a different event added via the on alias');
	});

	test('Removing listeners', function() {
		var ee = new EventEmitter();

		function testListener() {
			// Listener
		}

		function testListener2() {
			// Listener 2
		}

		ee.addListener('testEvent', testListener);
		equal(ee.listeners('testEvent')[0].type, 'testEvent', 'Retrieving the first listener');

		ee.addListener('testEvent', testListener2);
		equal(ee.listeners('testEvent')[1].type, 'testEvent', 'Retrieving the second listener');

		ee.removeListener('testEvent', testListener);
		equal(ee.listeners('testEvent')[1], undefined, 'Retrieving the second listener (should be gone)');
		equal(ee.listeners('testEvent')[0].listener, testListener2, 'First should now be the second');

		ee.removeListener('testEvent', testListener2);
		equal(ee.listeners('testEvent'), false, 'Retrieving any listeners (should be gone)');
	});
}());<|endoftext|>


<commit_before>var parseXlsx = require('../excelParser');
var assert = require('assert');

var sheetsDir = __dirname + '/spreadsheets';
var sheets = {
  'excel_mac_2011-basic.xlsx': [ [ 'One', 'Two' ], [ 'Three', 'Four' ] ],
  'excel_mac_2011-formatting.xlsx': [ [ 'Hey', 'now', 'so' ], [ 'cool', '', '' ] ]
};

describe('excel.js', function() {
  for (var filename in sheets) {
    (function(filename, expected) {

      describe(filename + ' basic test', function() {
        it('should return the right value', function(done) {
          parseXlsx(sheetsDir + '/' + filename, function(err, data) {
            assert.deepEqual(data, expected);
            done(err);
          });
        })
      });

    })(filename, sheets[filename]);
  }
});
<commit_msg>Add test for specifying the sheet<commit_after>var parseXlsx = require('../excelParser');
var assert = require('assert');

var sheetsDir = __dirname + '/spreadsheets';
var sheets = {
  'excel_mac_2011-basic.xlsx': [ [ 'One', 'Two' ], [ 'Three', 'Four' ] ],
  'excel_mac_2011-formatting.xlsx': [ [ 'Hey', 'now', 'so' ], [ 'cool', '', '' ] ]
};

describe('excel.js', function() {
  for (var filename in sheets) {
    (function(filename, expected) {

      describe(filename + ' basic test', function() {
        it('should return the right value', function(done) {
          parseXlsx(sheetsDir + '/' + filename, function(err, data) {
            assert.deepEqual(data, expected);
            done(err);
          });
        })
        it('should return the right value with the sheet specified', function(done) {
          parseXlsx(sheetsDir + '/' + filename, '1', function(err, data) {
            assert.deepEqual(data, expected);
            done(err);
          });
        })
      });

    })(filename, sheets[filename]);
  }
});
<|endoftext|>


<commit_before>var config = require('./config');
var manageUsers = require('./manageUsers.js');
var request = require('request');
//var mongo = require('./mongoFunctions.js');
var adm1 = config.adm1;
var adm2 = config.adm2;

function sendSubstitutions(senderID, message){
	var admMessage1 = {
		recipient: {
		  id: adm1
		},
		message: {
		  attachment:{
			  type: 'template',
			  payload:{
					template_type: 'button',
					text: 'nowa wiadomość:\n' + message,
					buttons:[
						{
							type: 'web_url',
							url: 'https://www.facebook.com/Zastępstwa-dla-szkół-573446562859405/messages',
							title: 'Odpowiedz'
						}
					]
			  }
		  }
		}
	};
	var admMessage2 = {
		recipient: {
		  id: adm2
		},
		message: {
		  attachment:{
			  type: 'template',
			  payload:{
					template_type: 'button',
					text: 'nowa wiadomość:\n' + message,
					buttons:[
						{
							type: 'web_url',
							url: 'https://www.facebook.com/Zastępstwa-dla-szkół-573446562859405/messages',
							title: 'Odpowiedz'
						}
					]
			  }
		  }
		}
	};
	var body = {
		'mode': 'classList',
		'param': 'today'
	};
	message = message.toLowerCase();
	var opt = message[0];
	var help = 'Dostępne polecenia to:\n"0 <klasa>" - zastępstwa dla klasy na dzisiaj\n"1 <klasa>" - zastępstwa dla klasy na jutro\n"2 <pytanie>" - pomoc';
	var messageData = {
		recipient: {
		  id: senderID
		},
		message: {
		  text: help
		}
	};
	var reqClass = message[2] + message[3];
	if(reqClass[1]=='g'){
		reqClass += message[4];
	}
	switch(opt){
		case '0':
			break;
		case '1':
			body['param']='tomorrow'; //masz else, więc jak dam dobrze to przejdzie, chociaż ty piszesz źle
			break;
		case '2':
			body['mode']='NO';
			var messageData = {
				recipient: {
				  id: senderID
				},
				message: {
				  text: 'Skontaktujemy się aby odpowiedzieć na pytanie.'
				}
			};
			callSendAPI(messageData);
			callSendAPI(admMessage1);
			callSendAPI(admMessage2);
			break;
		default:
			body['mode']='NO';
			callSendAPI(messageData);
			break;
	};
	if(body['mode'] != 'NO'){
		manageUsers.postCall('0000', body, function(classes){
			var is = 0;
			for(var i = 0; i < classes.length; i++){
				if(classes[i] == reqClass){
					is++;
				}
			}
			if(is > 0){
				var messageData = {
					recipient: {
					  id: senderID
					},
					message: {
					  attachment:{
						  type: 'template',
						  payload:{
								template_type: 'button',
								text: 'zastępstwa',
								buttons:[
									{
										type: 'web_url',
										url: 'https://domek.emadar.eu',
										title: 'Sprawdź na stronie'
									},
									{
										type: 'postback',
										title: 'Send on chat',
										payload: message
									}
								]
						  }
					  }
					}
				};
			} else {
				var messageData = {
					recipient: {
					  id: senderID
					},
					message: {
					  text: 'brak zastępstw'
					}
				};
			}
			callSendAPI(messageData);
		});
	}
}

function sendList(senderID, message){
	var body = {
		'mode': 'getChanges',
		'param': 'today'
	};
	if(payload[0]=='1'){
		body['param']='tomorrow';
	}
	var reqClass = message[2] + message[3];
	if(reqClass[1]=='g'){
		reqClass += message[4];
	}
	manageUsers.postCall('0000', body, function(obj){
		var subs = obj['substitution'];
		var msg = "";
		for(var i = 0; i < subs.length; i++){
			var oneSub = subs[i];
			if(oneSub.classes == reqClass){
				var changes = oneSub['changes'];
				if(oneSub.cancelled[0]){
					msg+='anulowanie';
				} else {
					msg+='Typ: ' + oneSub.substitution_types;
				}
				msg+='\nLekcja: ' + oneSub.periods;
				msg+='\nNauczyciel: ' + oneSub.teachers;
				if(changes){
					if(changes.teachers){
						msg+=' => ' + changes.teachers;
					}
				}
				msg+='\nPrzedmiot: ' + oneSub.subjects;
				if(changes){
					if(changes.subjects){
						msg+= ' => ' + changes.subjects;
					}
				}
				msg+='\nSala: ' + oneSub.classrooms;
				if(changes){
					if(changes.classrooms){
						msg+=' => ' + changes.classrooms;
					}
				}
				if(oneSub.groupnames){
					if(oneSub.groupnames != ""){
						msg+='\nGrupa: ' + oneSub.groupnames;
					}
				}
				if(oneSub.note){
					if(oneSub.note != ""){
						msg+='\nKomentarz: '  + oneSub.note;
					}
				}
				var messageData = {
					recipient: {
						id: senderID
					},
					message: {
						text: msg
					}
				};
				callSendAPI(messageData);
				msg='';
			}
		}
	});
}

function receivedPostback(event) {
	var senderID = event.sender.id;
	var recipientID = event.recipient.id;
	var timeOfPostback = event.timestamp;

	// The 'payload' param is a developer-defined field which is set in a postback
	// button for Structured Messages.
	var payload = event.postback.payload;

	console.log("Received postback for user %d and page %d with payload '%s' " +
	"at %d", senderID, recipientID, payload, timeOfPostback);

	sendList(senderID, payload);
}

function receivedMessage(event) {
	var senderID = event.sender.id;
	var recipientID = event.recipient.id;
	var timeOfMessage = event.timestamp;
	var message = event.message;

	console.log("Received message for user %d and page %d at %d with message:",
	senderID, recipientID, timeOfMessage);
	console.log(JSON.stringify(message));

	var messageId = message.mid;

	var messageText = message.text;
	var messageAttachments = message.attachments;
	var help = 'NIE PRZYJMUJEMY ZAŁĄCZNIKÓW\nDostępne polecenia to:\n"0 <klasa>" - zastępstwa dla klasy na dzisiaj\n"1 <klasa>" - zastępstwa dla klasy na jutro\n"2 <pytanie>" - pomoc';

	if (messageText) {
		sendSubstitutions(senderID, messageText);
	} else {
		var messageData = {
			recipient: {
			  id: senderID
			},
			message: {
			  text: help
			}
		};
		callSendAPI(messageData);
	}
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.7/me/messages',
    qs: { access_token: config.pageToken },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s",
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });
}

/*function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}*/

/*function sendGenericMessage(recipientId) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      attachment: {
        type: "template",
        payload: {
          template_type: "generic",
          elements: [{
            title: "rift",
            subtitle: "Next-generation virtual reality",
            item_url: "https://www.oculus.com/en-us/rift/",
            image_url: "http://messengerdemo.parseapp.com/img/rift.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/rift/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for first bubble",
            }],
          }, {
            title: "touch",
            subtitle: "Your Hands, Now in VR",
            item_url: "https://www.oculus.com/en-us/touch/",
            image_url: "http://messengerdemo.parseapp.com/img/touch.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/touch/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for second bubble",
            }]
          }]
        }
      }
    }
  };

  callSendAPI(messageData);
}*/

exports.receivedPostback=receivedPostback;
exports.receivedMessage=receivedMessage;
<commit_msg>one more fix<commit_after>var config = require('./config');
var manageUsers = require('./manageUsers.js');
var request = require('request');
//var mongo = require('./mongoFunctions.js');
var adm1 = config.adm1;
var adm2 = config.adm2;

function sendSubstitutions(senderID, message){
	var admMessage1 = {
		recipient: {
		  id: adm1
		},
		message: {
		  attachment:{
			  type: 'template',
			  payload:{
					template_type: 'button',
					text: 'nowa wiadomość:\n' + message,
					buttons:[
						{
							type: 'web_url',
							url: 'https://www.facebook.com/Zastępstwa-dla-szkół-573446562859405/messages',
							title: 'Odpowiedz'
						}
					]
			  }
		  }
		}
	};
	var admMessage2 = {
		recipient: {
		  id: adm2
		},
		message: {
		  attachment:{
			  type: 'template',
			  payload:{
					template_type: 'button',
					text: 'nowa wiadomość:\n' + message,
					buttons:[
						{
							type: 'web_url',
							url: 'https://www.facebook.com/Zastępstwa-dla-szkół-573446562859405/messages',
							title: 'Odpowiedz'
						}
					]
			  }
		  }
		}
	};
	var body = {
		'mode': 'classList',
		'param': 'today'
	};
	message = message.toLowerCase();
	var opt = message[0];
	var help = 'Dostępne polecenia to:\n"0 <klasa>" - zastępstwa dla klasy na dzisiaj\n"1 <klasa>" - zastępstwa dla klasy na jutro\n"2 <pytanie>" - pomoc';
	var messageData = {
		recipient: {
		  id: senderID
		},
		message: {
		  text: help
		}
	};
	var reqClass = message[2] + message[3];
	if(reqClass[1]=='g'){
		reqClass += message[4];
	}
	switch(opt){
		case '0':
			break;
		case '1':
			body['param']='tomorrow'; //masz else, więc jak dam dobrze to przejdzie, chociaż ty piszesz źle
			break;
		case '2':
			body['mode']='NO';
			var messageData = {
				recipient: {
				  id: senderID
				},
				message: {
				  text: 'Skontaktujemy się aby odpowiedzieć na pytanie.'
				}
			};
			callSendAPI(messageData);
			callSendAPI(admMessage1);
			callSendAPI(admMessage2);
			break;
		default:
			body['mode']='NO';
			callSendAPI(messageData);
			break;
	};
	if(body['mode'] != 'NO'){
		manageUsers.postCall('0000', body, function(classes){
			var is = 0;
			for(var i = 0; i < classes.length; i++){
				if(classes[i] == reqClass){
					is++;
				}
			}
			if(is > 0){
				var messageData = {
					recipient: {
					  id: senderID
					},
					message: {
					  attachment:{
						  type: 'template',
						  payload:{
								template_type: 'button',
								text: 'zastępstwa',
								buttons:[
									{
										type: 'web_url',
										url: 'https://domek.emadar.eu',
										title: 'Sprawdź na stronie'
									},
									{
										type: 'postback',
										title: 'Send on chat',
										payload: message
									}
								]
						  }
					  }
					}
				};
			} else {
				var messageData = {
					recipient: {
					  id: senderID
					},
					message: {
					  text: 'brak zastępstw'
					}
				};
			}
			callSendAPI(messageData);
		});
	}
}

function sendList(senderID, message){
	var body = {
		'mode': 'getChanges',
		'param': 'today'
	};
	if(message[0]=='1'){
		body['param']='tomorrow';
	}
	var reqClass = message[2] + message[3];
	if(reqClass[1]=='g'){
		reqClass += message[4];
	}
	manageUsers.postCall('0000', body, function(obj){
		var subs = obj['substitution'];
		var msg = "";
		for(var i = 0; i < subs.length; i++){
			var oneSub = subs[i];
			if(oneSub.classes == reqClass){
				var changes = oneSub['changes'];
				if(oneSub.cancelled[0]){
					msg+='anulowanie';
				} else {
					msg+='Typ: ' + oneSub.substitution_types;
				}
				msg+='\nLekcja: ' + oneSub.periods;
				msg+='\nNauczyciel: ' + oneSub.teachers;
				if(changes){
					if(changes.teachers){
						msg+=' => ' + changes.teachers;
					}
				}
				msg+='\nPrzedmiot: ' + oneSub.subjects;
				if(changes){
					if(changes.subjects){
						msg+= ' => ' + changes.subjects;
					}
				}
				msg+='\nSala: ' + oneSub.classrooms;
				if(changes){
					if(changes.classrooms){
						msg+=' => ' + changes.classrooms;
					}
				}
				if(oneSub.groupnames){
					if(oneSub.groupnames != ""){
						msg+='\nGrupa: ' + oneSub.groupnames;
					}
				}
				if(oneSub.note){
					if(oneSub.note != ""){
						msg+='\nKomentarz: '  + oneSub.note;
					}
				}
				var messageData = {
					recipient: {
						id: senderID
					},
					message: {
						text: msg
					}
				};
				callSendAPI(messageData);
				msg='';
			}
		}
	});
}

function receivedPostback(event) {
	var senderID = event.sender.id;
	var recipientID = event.recipient.id;
	var timeOfPostback = event.timestamp;

	// The 'payload' param is a developer-defined field which is set in a postback
	// button for Structured Messages.
	var payload = event.postback.payload;

	console.log("Received postback for user %d and page %d with payload '%s' " +
	"at %d", senderID, recipientID, payload, timeOfPostback);

	sendList(senderID, payload);
}

function receivedMessage(event) {
	var senderID = event.sender.id;
	var recipientID = event.recipient.id;
	var timeOfMessage = event.timestamp;
	var message = event.message;

	console.log("Received message for user %d and page %d at %d with message:",
	senderID, recipientID, timeOfMessage);
	console.log(JSON.stringify(message));

	var messageId = message.mid;

	var messageText = message.text;
	var messageAttachments = message.attachments;
	var help = 'NIE PRZYJMUJEMY ZAŁĄCZNIKÓW\nDostępne polecenia to:\n"0 <klasa>" - zastępstwa dla klasy na dzisiaj\n"1 <klasa>" - zastępstwa dla klasy na jutro\n"2 <pytanie>" - pomoc';

	if (messageText) {
		sendSubstitutions(senderID, messageText);
	} else {
		var messageData = {
			recipient: {
			  id: senderID
			},
			message: {
			  text: help
			}
		};
		callSendAPI(messageData);
	}
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.7/me/messages',
    qs: { access_token: config.pageToken },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s",
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });
}

/*function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}*/

/*function sendGenericMessage(recipientId) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      attachment: {
        type: "template",
        payload: {
          template_type: "generic",
          elements: [{
            title: "rift",
            subtitle: "Next-generation virtual reality",
            item_url: "https://www.oculus.com/en-us/rift/",
            image_url: "http://messengerdemo.parseapp.com/img/rift.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/rift/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for first bubble",
            }],
          }, {
            title: "touch",
            subtitle: "Your Hands, Now in VR",
            item_url: "https://www.oculus.com/en-us/touch/",
            image_url: "http://messengerdemo.parseapp.com/img/touch.png",
            buttons: [{
              type: "web_url",
              url: "https://www.oculus.com/en-us/touch/",
              title: "Open Web URL"
            }, {
              type: "postback",
              title: "Call Postback",
              payload: "Payload for second bubble",
            }]
          }]
        }
      }
    }
  };

  callSendAPI(messageData);
}*/

exports.receivedPostback=receivedPostback;
exports.receivedMessage=receivedMessage;
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */
var pkginfo = require('pkginfo')
  , uri = require('url')
  , path = require('path')
  , fs = require('fs')
  , utils = require('../utils')
  , existsSync = fs.existsSync || path.existsSync; // <=0.6

var SCRIPT_RUNNERS = [ '_mocha' ];

/**
 * Component-ized boot phase that announces services.
 *
 * To utilize this component within an application, configure the IoC loader
 * to use common service discovery components.
 *
 *     IoC.loader(require('bixby-sd'));
 *
 * @param {Settings} settings
 * @param {Logger} logger
 * @return {Function}
 */
exports = module.exports = function(registry, settings, logger) {

  return function announce(done) {
    var config = settings.get('sd') || {};
    if (!config.domain) { throw new Error('Misconfigured service announcement: missing domain'); }

    var root = path.dirname(pkginfo.find(require.main))
      , fsegs = require.main.filename.split('/')
    if (fsegs[fsegs.length - 1].indexOf(SCRIPT_RUNNERS) !== -1) {
      root = process.cwd();
      console.log(root);
    }
    var file = path.resolve(root, 'app/services.json')
      , domain = config.domain
      , port, address, protocol
      , addresses;

    if (!existsSync(file)) { return done(new Error('No such file "' + file + '"')); }

    if (this.httpServer || this.httpsServer) {
      var server = this.httpsServer || this.httpServer
        , addr = server.address();

      protocol = this.httpsServer ? 'https' : 'http';
      address = addr.address
      port = addr.port
    } else {
      return done(new Error('Unable to determine address of server'));
    }

    if (address == '0.0.0.0') {
      addresses = utils.ips('IPv4');
    } else {
      addresses = [ address ];
    }

    var data = fs.readFileSync(file, 'utf8')
      , services;
    try {
      services = JSON.parse(data);
    } catch (_) {
      return done(new Error('Failed to parse services'));
    }

    // For each service offered by the application, announce it's availability
    // on all addresses.
    var types = Object.keys(services)
      , sidx = 0;

    function siter(err) {
      if (err) { return done(err); }

      var type = types[sidx++];
      if (!type) { return done(); }

      var target = services[type]
        , aidx = 0;

      function aiter(err) {
        if (err) { return siter(err); }

        var address = addresses[aidx++];
        if (!address) { return siter(); }

        var record;
        if (typeof target == 'boolean') {
          if (/^[a-f0-9:]+$/.test(address)) {
            record = '[' + address + ']:' + port;  // IPv6
          } else {
            record = address + ':' + port;  // IPv4
          }
        } else if (typeof target == 'string') {
          record = uri.format({ protocol: protocol, hostname: address, port: port, pathname: target });
        } else {
          aiter(new Error('Invalid record for service "' + type + '"'));
        }

        logger.info('Announcing service %s in %s at %s', type, domain, record);
        registry.announce(domain, type, record, function(err) {
          if (err) { return aiter(err); }
          return aiter();
        });
      }
      aiter();
    }
    siter();
  }
}

/**
 * Component annotations.
 */
exports['@require'] = [ '../registry', 'settings', 'logger' ];
<commit_msg>Update announce.js<commit_after>/**
 * Module dependencies.
 */
var pkginfo = require('pkginfo')
  , uri = require('url')
  , path = require('path')
  , fs = require('fs')
  , utils = require('../utils')
  , existsSync = fs.existsSync || path.existsSync; // <=0.6

var SCRIPT_RUNNERS = [ '_mocha' ];

/**
 * Component-ized boot phase that announces services.
 *
 * To utilize this component within an application, configure the IoC loader
 * to use common service discovery components.
 *
 *     IoC.loader(require('bixby-sd'));
 *
 * @param {Settings} settings
 * @param {Logger} logger
 * @return {Function}
 */
exports = module.exports = function(registry, settings, logger) {

  return function announce(done) {
    var config = settings.get('sd') || {};
    if (!config.domain) { throw new Error('Misconfigured service announcement: missing domain'); }

    var root = path.dirname(pkginfo.find(require.main))
      , fsegs = require.main.filename.split('/');
    if (fsegs[fsegs.length - 1].indexOf(SCRIPT_RUNNERS) !== -1) {
      root = process.cwd();
      console.log(root);
    }
    var file = path.resolve(root, 'app/services.json')
      , domain = config.domain
      , port, address, protocol
      , addresses;

    if (!existsSync(file)) { return done(new Error('No such file "' + file + '"')); }

    if (this.httpServer || this.httpsServer) {
      var server = this.httpsServer || this.httpServer
        , addr = server.address();

      protocol = this.httpsServer ? 'https' : 'http';
      address = addr.address
      port = addr.port
    } else {
      return done(new Error('Unable to determine address of server'));
    }

    if (address == '0.0.0.0') {
      addresses = utils.ips('IPv4');
    } else {
      addresses = [ address ];
    }

    var data = fs.readFileSync(file, 'utf8')
      , services;
    try {
      services = JSON.parse(data);
    } catch (_) {
      return done(new Error('Failed to parse services'));
    }

    // For each service offered by the application, announce it's availability
    // on all addresses.
    var types = Object.keys(services)
      , sidx = 0;

    function siter(err) {
      if (err) { return done(err); }

      var type = types[sidx++];
      if (!type) { return done(); }

      var target = services[type]
        , aidx = 0;

      function aiter(err) {
        if (err) { return siter(err); }

        var address = addresses[aidx++];
        if (!address) { return siter(); }

        var record;
        if (typeof target == 'boolean') {
          if (/^[a-f0-9:]+$/.test(address)) {
            record = '[' + address + ']:' + port;  // IPv6
          } else {
            record = address + ':' + port;  // IPv4
          }
        } else if (typeof target == 'string') {
          record = uri.format({ protocol: protocol, hostname: address, port: port, pathname: target });
        } else {
          aiter(new Error('Invalid record for service "' + type + '"'));
        }

        logger.info('Announcing service %s in %s at %s', type, domain, record);
        registry.announce(domain, type, record, function(err) {
          if (err) { return aiter(err); }
          return aiter();
        });
      }
      aiter();
    }
    siter();
  }
}

/**
 * Component annotations.
 */
exports['@require'] = [ '../registry', 'settings', 'logger' ];
<|endoftext|>