<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2018 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

import {combineReducers} from 'redux';

import camelizeKeys from 'indico/utils/camelize';
import {requestReducer} from 'indico/utils/redux';
import * as roomsActions from './actions';

export default combineReducers({
    requests: combineReducers({
        // global data
        equipmentTypes: requestReducer(
            roomsActions.FETCH_EQUIPMENT_TYPES_REQUEST,
            roomsActions.FETCH_EQUIPMENT_TYPES_SUCCESS,
            roomsActions.FETCH_EQUIPMENT_TYPES_ERROR
        ),
        // room-specific data
        rooms: requestReducer(
            roomsActions.FETCH_ROOMS_REQUEST,
            roomsActions.FETCH_ROOMS_SUCCESS,
            roomsActions.FETCH_ROOMS_ERROR
        ),
        availability: requestReducer(
            roomsActions.FETCH_AVAILABILITY_REQUEST,
            roomsActions.FETCH_AVAILABILITY_SUCCESS,
            roomsActions.FETCH_AVAILABILITY_ERROR
        ),
        attributes: requestReducer(
            roomsActions.FETCH_ATTRIBUTES_REQUEST,
            roomsActions.FETCH_ATTRIBUTES_SUCCESS,
            roomsActions.FETCH_ATTRIBUTES_ERROR
        ),
    }),
    equipmentTypes: (state = [], action) => {
        switch (action.type) {
            case roomsActions.EQUIPMENT_TYPES_RECEIVED:
                return action.data.map(x => camelizeKeys(x));
            default:
                return state;
        }
    },
    rooms: (state = {}, action) => {
        switch (action.type) {
            case roomsActions.ROOMS_RECEIVED:
                return action.data;
            default:
                return state;
        }
    },
    availability: (state = {}, action) => {
        switch (action.type) {
            case roomsActions.AVAILABILITY_RECEIVED: {
                const {id, availability} = action.data;
                return {...state, [id]: availability};
            }
            default:
                return state;
        }
    },
    attributes: (state = {}, action) => {
        switch (action.type) {
            case roomsActions.ATTRIBUTES_RECEIVED: {
                const {id, attributes} = action.data;
                return {...state, [id]: attributes};
            }
            default:
                return state;
        }
    },
});
<commit_msg>Properly update RoomDetails availability state<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2018 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

import {combineReducers} from 'redux';

import camelizeKeys from 'indico/utils/camelize';
import {requestReducer} from 'indico/utils/redux';
import * as roomsActions from './actions';
import {actions as bookingActions} from '../bookings';
import {actions as bookRoomActions} from '../../modules/bookRoom';

function filterAvailability(roomAvailability, bookingId) {
    return roomAvailability.map((availability) => {
        const bookings = availability.bookings || [];
        const newBookings = bookings.filter((booking) => {
            return booking.reservation.id !== bookingId;
        });
        return {...availability, bookings: newBookings};
    });
}

export default combineReducers({
    requests: combineReducers({
        // global data
        equipmentTypes: requestReducer(
            roomsActions.FETCH_EQUIPMENT_TYPES_REQUEST,
            roomsActions.FETCH_EQUIPMENT_TYPES_SUCCESS,
            roomsActions.FETCH_EQUIPMENT_TYPES_ERROR
        ),
        // room-specific data
        rooms: requestReducer(
            roomsActions.FETCH_ROOMS_REQUEST,
            roomsActions.FETCH_ROOMS_SUCCESS,
            roomsActions.FETCH_ROOMS_ERROR
        ),
        availability: requestReducer(
            roomsActions.FETCH_AVAILABILITY_REQUEST,
            roomsActions.FETCH_AVAILABILITY_SUCCESS,
            roomsActions.FETCH_AVAILABILITY_ERROR
        ),
        attributes: requestReducer(
            roomsActions.FETCH_ATTRIBUTES_REQUEST,
            roomsActions.FETCH_ATTRIBUTES_SUCCESS,
            roomsActions.FETCH_ATTRIBUTES_ERROR
        ),
    }),
    equipmentTypes: (state = [], action) => {
        switch (action.type) {
            case roomsActions.EQUIPMENT_TYPES_RECEIVED:
                return action.data.map(x => camelizeKeys(x));
            default:
                return state;
        }
    },
    rooms: (state = {}, action) => {
        switch (action.type) {
            case roomsActions.ROOMS_RECEIVED:
                return action.data;
            default:
                return state;
        }
    },
    availability: (state = {}, action) => {
        switch (action.type) {
            case roomsActions.AVAILABILITY_RECEIVED: {
                const {id, availability} = action.data;
                return {...state, [id]: availability};
            }
            case bookRoomActions.CREATE_BOOKING_SUCCESS: {
                const {bookings, roomId} = camelizeKeys(action.data);
                const {[roomId]: roomAvailability} = state;

                const av = roomAvailability.map((roomAv) => {
                    if (!(roomAv.day in bookings)) {
                        return roomAv;
                    }

                    const oldBookings = roomAv.bookings || [];
                    return {...roomAv, bookings: [...oldBookings, ...bookings[roomAv.day]]};
                });

                return {...state, [roomId]: av};
            }
            case bookingActions.BOOKING_STATE_UPDATED: {
                const {booking: {id, roomId}, bookingState} = camelizeKeys(action.data);
                if (bookingState === 'rejected' || bookingState === 'cancelled') {
                    const {[roomId]: roomAvailability} = state;
                    if (!roomAvailability) {
                        return state;
                    }
                    return {...state, [roomId]: filterAvailability(roomAvailability, id)};
                }

                return state;
            }
            case bookingActions.DELETE_BOOKING_SUCCESS: {
                const {roomId, bookingId} = camelizeKeys(action.data);
                const {[roomId]: roomAvailability} = state;
                if (!roomAvailability) {
                    return state;
                }
                return {...state, [roomId]: filterAvailability(roomAvailability, bookingId)};
            }
            default:
                return state;
        }
    },
    attributes: (state = {}, action) => {
        switch (action.type) {
            case roomsActions.ATTRIBUTES_RECEIVED: {
                const {id, attributes} = action.data;
                return {...state, [id]: attributes};
            }
            default:
                return state;
        }
    },
});
<|endoftext|>


<commit_before>import React from 'react';

import GraphQLWebClient from './GraphQLWebClient';

var styles = {
    clear: {clear: "both"}
};

export default class GraphQLWebClientWrapper extends React.Component {
  constructor(props) {
    super(props);
    var endpoint = this.props.endpoint;
    if (window && window.location.search) {
      var m = window.location.search.match(/endpoint=(.+)/)[1];
      if (m) { endpoint = m; }
    }
    this.state = {
      endpoint: endpoint,
      cannedQueries: [
        `{ __schema__ { root_fields { name, description } } }`,
        `{ __types { name, description} }`,
        `{ __types { name, description, fields { name, description } } }`,
        `{ _User { __type__ { fields { name } } } }`
      ]
    };
    this.state.defaultQuery = this.state.cannedQueries[0];
    if (window.location.hash.length > 1) {
      this.state.defaultQuery = decodeURIComponent(window.location.hash.slice(1));
    }
  }
  onChange(event) {
    this.setState({endpoint: event.target.value});
  }
  onCannedQueryClicked(event) {
    this.setState({defaultQuery: event.target.text});
  }
  render() {
    var cannedQueries = this.state.cannedQueries.map((query) => {
      return (

{query}

      );
    });
    return (

graphql client

        graphql endpoint:
        <input size="50" defaultValue={this.state.endpoint} onChange={this.onChange.bind(this)} />

        <GraphQLWebClient
          defaultQuery={this.state.defaultQuery}
          endpoint={this.state.endpoint}
        />

Canned Queries:

          {cannedQueries}

    );
  }
}
<commit_msg>Add __typename, move __types under __schema__<commit_after>import React from 'react';

import GraphQLWebClient from './GraphQLWebClient';

var styles = {
    clear: {clear: "both"}
};

export default class GraphQLWebClientWrapper extends React.Component {
  constructor(props) {
    super(props);
    var endpoint = this.props.endpoint;
    if (window && window.location.search) {
      var m = window.location.search.match(/endpoint=(.+)/)[1];
      if (m) { endpoint = m; }
    }
    this.state = {
      endpoint: endpoint,
      cannedQueries: [
        `{ __schema__ { root_fields { name, description } } }`,
        `{ __schema__ { types { name, description } } }`,
        `{ __schema__ { types { name, description, fields { name, description } } } }`,
        `{ _User { __type__ { fields { name } } } }`
      ]
    };
    this.state.defaultQuery = this.state.cannedQueries[0];
    if (window.location.hash.length > 1) {
      this.state.defaultQuery = decodeURIComponent(window.location.hash.slice(1));
    }
  }
  onChange(event) {
    this.setState({endpoint: event.target.value});
  }
  onCannedQueryClicked(event) {
    this.setState({defaultQuery: event.target.text});
  }
  render() {
    var cannedQueries = this.state.cannedQueries.map((query) => {
      return (

{query}

      );
    });
    return (

graphql client

        graphql endpoint:
        <input size="50" defaultValue={this.state.endpoint} onChange={this.onChange.bind(this)} />

        <GraphQLWebClient
          defaultQuery={this.state.defaultQuery}
          endpoint={this.state.endpoint}
        />

Canned Queries:

          {cannedQueries}

    );
  }
}
<|endoftext|>


<commit_before>/*!
 *  Chinachu Common Module (node-chinachu-common)
 *
 *  Copyright (c) 2012 Yuki KAN and Chinachu Project Contributors
 *  http://chinachu.akkar.in/
**/
/*jslint node:true, nomen:true, plusplus:true, regexp:true, vars:true, continue:true */
'use strict';

var fs         = require('fs');
var crypto     = require('crypto');
var dateFormat = require('dateformat');
var child_process = require('child_process');
var string = require('string');

var execSync   = function (command) {
	try {
		return child_process.execSync(command, { encoding: 'utf8' });
	} catch (e) {
	}
};

exports.jsonWatcher = function (filepath, callback, option) {
	if (typeof option === 'undefined') { option = {}; }

	option.wait = option.wait || 1000;

	if (!fs.existsSync(filepath)) {
		if (option.create) {
			fs.writeFileSync(filepath, JSON.stringify(option.create));
		} else {
			callback('FATAL: `' + filepath + '` is not exists.', null, null);
			return;
		}
	}

	var data = null;

	var parse = function (err, json) {
		if (err) {
			callback('WARN: Failed to read `' + filepath + '`. (' + err + ')', null, null);
		} else {
			data = null;

			try {
				data = JSON.parse(json);
				callback(null, data, 'READ: `' + filepath + '` is updated.');
			} catch (e) {
				callback('WARN: `' + filepath + '` is invalid. (' + e + ')', null, null);
			}
		}
	};

	var timer = null;

	var read = function () {
		timer = null;

		fs.readFile(filepath, { encoding: 'utf8' }, parse);
	};

	if (option.now) { read(); }

	var onUpdated = function () {
		if (timer !== null) { clearTimeout(timer); }
		timer = setTimeout(read, option.wait);
	};
	fs.watch(filepath, onUpdated);
};

exports.getProgramById = function (id, array) {
	if (!array || array.length === 0) {
		return null;
	}

	if (array[0].programs) {
		array = (function () {
			var programs = [];

			array.forEach(function (ch) {
				programs = programs.concat(ch.programs);
			});

			return programs;
		}());
	}

	return (function () {
		var x = null;

		array.forEach(function (a) {
			if (a.id === id) { x = a; }
		});

		return x;
	}());
};

exports.existsTuner = function (tuners, type, callback) {

	process.nextTick(function () {
		callback(exports.existsTunerSync(tuners, type));
	});
};

exports.existsTunerSync = function (tuners, type) {

	var j, tuner, isExists = false;

	for (j = 0; tuners.length > j; j++) {
		tuner = tuners[j];
		tuner.n = j;

		if (tuner.types.indexOf(type) !== -1) {
			isExists = true;
			break;
		}
	}

	return isExists;
};

exports.getFreeTunerSync = function (tuners, type, isEpg, priority) {

	var j, exists, pid, tuner, freeTuner = null;

	priority = priority || 0;

	for (j = 0; tuners.length > j; j++) {
		tuner = tuners[j];
		tuner.n = j;

		if (tuner.types.indexOf(type) === -1) {
			continue;
		}

		if (isEpg === true && tuner.noEpg === true) {
			continue;
		}

		if (fs.existsSync('./data/tuner.' + j + '.lock') === true) {
			pid = fs.readFileSync('./data/tuner.' + j + '.lock', { encoding: 'utf8' });
			pid = pid.trim();

			if (pid === '') {
				continue;
			}

			if (fs.existsSync('./data/tuner.' + j + '.priority') === true) {
				var tunerPriority = fs.readFileSync('./data/tuner.' + j + '.priority', { encoding: 'utf8' });
				tunerPriority = tunerPriority.trim();

				// higher priority than locked tuner
				if (priority > tunerPriority) {
					// force terminate the process
					exports.unlockTunerSync(tuner);
					execSync('kill -KILL ' + pid);
					freeTuner = tuner;
					break;
				}
			}

			if (execSync('kill -0 ' + pid) !== '') {
				exports.unlockTunerSync(tuner);
				freeTuner = tuner;
				break;
			}
		} else {
			freeTuner = tuner;
			break;
		}
	}

	return freeTuner;
};

exports.lockTunerSync = function (tuner, priority) {
	try {
		priority = priority || 0;
		fs.writeFileSync('./data/tuner.' + tuner.n + '.priority', priority, { flag: 'wx' });
		return fs.writeFileSync('./data/tuner.' + tuner.n + '.lock', process.pid, { flag: 'wx' });
	} catch (e) {
		throw e;
	}
};

exports.unlockTuner = function (tuner, callback) {
	if (fs.existsSync('./data/tuner.' + tuner.n + '.priority')) {
		fs.unlinkSync('./data/tuner.' + tuner.n + '.priority');
	}
	fs.unlink('./data/tuner.' + tuner.n + '.lock', callback);
};

exports.unlockTunerSync = function (tuner, safe) {
	try {
		if (safe === true) {
			var pid = fs.readFileSync('./data/tuner.' + tuner.n + '.lock', { encoding: 'utf8' });
			if (pid !== '') {
				if (execSync('kill -0 ' + pid) === '') {
					return null;
				} else {
					if (fs.existsSync('./data/tuner.' + tuner.n + '.priority')) {
						fs.unlinkSync('./data/tuner.' + tuner.n + '.priority');
					}
					return fs.unlinkSync('./data/tuner.' + tuner.n + '.lock');
				}
			}
		}
		if (fs.existsSync('./data/tuner.' + tuner.n + '.priority')) {
			fs.unlinkSync('./data/tuner.' + tuner.n + '.priority');
		}
		return fs.unlinkSync('./data/tuner.' + tuner.n + '.lock');
	} catch (e) {
		throw e;
	}
};

exports.writeTunerPidSync = function (tuner, pid, priority) {
	try {
		priority = priority || 0;
		fs.writeFileSync('./data/tuner.' + tuner.n + '.priority', priority, { flag: 'w' });
		return fs.writeFileSync('./data/tuner.' + tuner.n + '.lock', pid, { flag: 'w' });
	} catch (e) {
		throw e;
	}
};

var Countdown = function (count, callback) {
	this.c = count;
	this.f = callback;
};

Countdown.prototype = {
	tick: function () {

		--this.c;

		if (this.c === 0) {
			this.f();
		}

		return this;
	}
};

exports.createCountdown = function (a, b) {
	return new Countdown(a, b);
};

exports.createTimeout = function (a, b) {
	return function () {
		return setTimeout(a, b);
	};
};

exports.formatRecordedName = function (program, name) {
	name = name.replace(/<([^>]+)>/g, function (z, a) {

		// date:
		if (a.match(/^date:.+$/) !== null) { return dateFormat(new Date(program.start), a.match(/:(.+)$/)[1]); }

		// id
		if (a.match(/^id$/) !== null) { return program.id; }

		// type
		if (a.match(/^type$/) !== null) { return program.channel.type; }

		// channel
		if (a.match(/^channel$/) !== null) { return program.channel.channel; }

		// channel-id
		if (a.match(/^channel-id$/) !== null) { return program.channel.id; }

		// channel-sid
		if (a.match(/^channel-sid$/) !== null) { return program.channel.sid; }

		// channel-name
		if (a.match(/^channel-name$/) !== null) { return exports.stripFilename(program.channel.name); }

		// tuner
		if (a.match(/^tuner$/) !== null) { return program.tuner.name; }

		// title
		if (a.match(/^title$/) !== null) { return exports.stripFilename(program.title); }

		// fulltitle
		if (a.match(/^fulltitle$/) !== null) { return exports.stripFilename(program.fullTitle || ''); }

		// subtitle
		if (a.match(/^subtitle$/) !== null) { return exports.stripFilename(program.subTitle || ''); }

		// episode (zero-padded)
		if (a.match(/^episode:\d+$/) !== null) {
			var digit = a.match(/\d+/)[0];
			if (isNaN(digit)) {
				digit = 1;
			}
			return program.episode === null ? 'n' : string(program.episode.toString(10)).padLeft(digit, '0').s;
		}

		// episode
		if (a.match(/^episode$/) !== null) { return program.episode || 'n'; }

		// category
		if (a.match(/^category$/) !== null) { return program.category; }
	});

	return name;
};

// strip
exports.stripFilename = function (a) {

	a = a.replace(/\//g, '／').replace(/\\/g, '＼').replace(/:/g, '：').replace(/\*/g, '＊').replace(/\?/g, '？');
	a = a.replace(/"/g, '”').replace(/</g, '＜').replace(/>/g, '＞').replace(/\|/g, '｜').replace(/≫/g, '＞＞');

	return a;
};

// 全ルールとのマッチ判定
exports.isMatchedProgram = function (rules, program) {
	var i;
	for (i = 0; i < rules.length; i++) {
		if (exports.programMatchesRule(rules[i], program)) {
			return true;
		}
	}

	return false;
};

// 単体のルールとのマッチ判定
exports.programMatchesRule = function (rule, program) {
	var i, j, l, m, isFound;

	// isDisabled
	if (rule.isDisabled) { return false; }

	// sid
	if (rule.sid && rule.sid !== program.channel.sid) { return false; }

	// types
	if (rule.types) {
		if (rule.types.indexOf(program.channel.type) === -1) { return false; }
	}

	// channels
	if (rule.channels) {
		if (rule.channels.indexOf(program.channel.id) === -1) {
			if (rule.channels.indexOf(program.channel.channel) === -1) {
				return false;
			}
		}
	}

	// ignore_channels
	if (rule.ignore_channels) {
		if (rule.ignore_channels.indexOf(program.channel.id) !== -1) {
			return false;
		}
		if (rule.ignore_channels.indexOf(program.channel.channel) !== -1) {
			return false;
		}
	}

	// category
	if (rule.category && rule.category !== program.category) { return false; }

	// categories
	if (rule.categories) {
		if (rule.categories.indexOf(program.category) === -1) { return false; }
	}

	// hour
	if (rule.hour && (typeof rule.hour.start === 'number') && (typeof rule.hour.end === 'number') && !(rule.hour.start === 0 && rule.hour.end === 24)) {
		var ruleStart = rule.hour.start;
		var ruleEnd   = rule.hour.end;

		var progStart = new Date(program.start).getHours();
		var progEnd   = new Date(program.end).getHours();
		var progEndMinute = new Date(program.end).getMinutes();

		if (progStart > progEnd) {
			progEnd += 24;
		}
		if (progEndMinute === 0) {
			progEnd -= 1;
		}

		if (ruleStart > ruleEnd) {
			if ((ruleStart > progStart) && (ruleEnd < progEnd)) { return false; }
		} else {
			if ((ruleStart > progStart) || (ruleEnd < progEnd)) { return false; }
		}
	}

	// duration
	if (rule.duration && (typeof rule.duration.min !== 'undefined') && (typeof rule.duration.max !== 'undefined')) {
		if ((rule.duration.min > program.seconds) || (rule.duration.max < program.seconds)) { return false; }
	}

	// reserve_titles
	if (rule.reserve_titles) {
		isFound = false;

		for (i = 0; i < rule.reserve_titles.length; i++) {
			if (program.fullTitle.match(rule.reserve_titles[i]) !== null) { isFound = true; }
		}

		if (!isFound) { return false; }
	}

	// ignore_titles
	if (rule.ignore_titles) {
		for (i = 0; i < rule.ignore_titles.length; i++) {
			if (program.fullTitle.match(rule.ignore_titles[i]) !== null) { return false; }
		}
	}

	// reserve_descriptions
	if (rule.reserve_descriptions) {
		if (!program.detail) { return false; }

		isFound = false;

		for (i = 0; i < rule.reserve_descriptions.length; i++) {
			if (program.detail.match(rule.reserve_descriptions[i]) !== null) { isFound = true; }
		}

		if (!isFound) { return false; }
	}

	// ignore_descriptions
	if (rule.ignore_descriptions) {
		if (!program.detail) { return false; }

		for (i = 0; i < rule.ignore_descriptions.length; i++) {
			if (program.detail.match(rule.ignore_descriptions[i]) !== null) { return false; }
		}
	}

	// ignore_flags
	if (rule.ignore_flags) {
		for (i = 0; i < rule.ignore_flags.length; i++) {
			for (j = 0; j < program.flags.length; j++) {
				if (rule.ignore_flags[i] === program.flags[j]) { return false; }
			}
		}
	}

	// reserve_flags
	if (rule.reserve_flags) {
		if (!program.flags) { return false; }

		isFound = false;

		for (i = 0; i < rule.reserve_flags.length; i++) {
			for (j = 0; j < program.flags.length; j++) {
				if (rule.reserve_flags[i] === program.flags[j]) { isFound = true; }
			}
		}

		if (!isFound) { return false; }
	}

	return true;
};
<commit_msg>Seek the lowest priority of tuner will be free<commit_after>/*!
 *  Chinachu Common Module (node-chinachu-common)
 *
 *  Copyright (c) 2012 Yuki KAN and Chinachu Project Contributors
 *  http://chinachu.akkar.in/
**/
/*jslint node:true, nomen:true, plusplus:true, regexp:true, vars:true, continue:true */
'use strict';

var fs         = require('fs');
var crypto     = require('crypto');
var dateFormat = require('dateformat');
var child_process = require('child_process');
var string = require('string');

var execSync   = function (command) {
	try {
		return child_process.execSync(command, { encoding: 'utf8' });
	} catch (e) {
	}
};

exports.jsonWatcher = function (filepath, callback, option) {
	if (typeof option === 'undefined') { option = {}; }

	option.wait = option.wait || 1000;

	if (!fs.existsSync(filepath)) {
		if (option.create) {
			fs.writeFileSync(filepath, JSON.stringify(option.create));
		} else {
			callback('FATAL: `' + filepath + '` is not exists.', null, null);
			return;
		}
	}

	var data = null;

	var parse = function (err, json) {
		if (err) {
			callback('WARN: Failed to read `' + filepath + '`. (' + err + ')', null, null);
		} else {
			data = null;

			try {
				data = JSON.parse(json);
				callback(null, data, 'READ: `' + filepath + '` is updated.');
			} catch (e) {
				callback('WARN: `' + filepath + '` is invalid. (' + e + ')', null, null);
			}
		}
	};

	var timer = null;

	var read = function () {
		timer = null;

		fs.readFile(filepath, { encoding: 'utf8' }, parse);
	};

	if (option.now) { read(); }

	var onUpdated = function () {
		if (timer !== null) { clearTimeout(timer); }
		timer = setTimeout(read, option.wait);
	};
	fs.watch(filepath, onUpdated);
};

exports.getProgramById = function (id, array) {
	if (!array || array.length === 0) {
		return null;
	}

	if (array[0].programs) {
		array = (function () {
			var programs = [];

			array.forEach(function (ch) {
				programs = programs.concat(ch.programs);
			});

			return programs;
		}());
	}

	return (function () {
		var x = null;

		array.forEach(function (a) {
			if (a.id === id) { x = a; }
		});

		return x;
	}());
};

exports.existsTuner = function (tuners, type, callback) {

	process.nextTick(function () {
		callback(exports.existsTunerSync(tuners, type));
	});
};

exports.existsTunerSync = function (tuners, type) {

	var j, tuner, isExists = false;

	for (j = 0; tuners.length > j; j++) {
		tuner = tuners[j];
		tuner.n = j;

		if (tuner.types.indexOf(type) !== -1) {
			isExists = true;
			break;
		}
	}

	return isExists;
};

exports.getFreeTunerSync = function (tuners, type, isEpg, priority) {

	var j, exists, pid, tuner, freeTuner = null, tunerWillBeUnlocked = null;

	priority = priority || 0;

	for (j = 0; tuners.length > j; j++) {
		tuner = tuners[j];
		tuner.n = j;

		if (tuner.types.indexOf(type) === -1) {
			continue;
		}

		if (isEpg === true && tuner.noEpg === true) {
			continue;
		}

		if (fs.existsSync('./data/tuner.' + j + '.lock') === true) {
			pid = fs.readFileSync('./data/tuner.' + j + '.lock', { encoding: 'utf8' });
			pid = pid.trim();

			if (pid === '') {
				continue;
			}

			if (execSync('kill -0 ' + pid) !== '') {
				exports.unlockTunerSync(tuner);
				freeTuner = tuner;
				break;
			}

			if (fs.existsSync('./data/tuner.' + j + '.priority') === true) {
				var tunerPriority = fs.readFileSync('./data/tuner.' + j + '.priority', { encoding: 'utf8' });
				tunerPriority = tunerPriority.trim();

				// Seek the lowest priority
				if (priority > tunerPriority) {
					tunerWillBeUnlocked = tuner;
					if (tunerPriority === 0) {
						break;
					}
					priority = tunerPriority;
					continue;
				} else {
					continue;
				}
			}
		} else {
			freeTuner = tuner;
			break;
		}
	}

	if (tunerWillBeUnlocked !== null && freeTuner === null) {
		tuner = tunerWillBeUnlocked;
		pid = fs.readFileSync('./data/tuner.' + tuner.n + '.lock', { encoding: 'utf8' });
		pid = pid.trim();

		// force terminate the process
		execSync('kill -KILL ' + pid);
		try {
			// If cleanup is not completed
			exports.unlockTunerSync(tuner);
		} catch(e) {
		}
		freeTuner = tuner;
	}

	return freeTuner;
};

exports.lockTunerSync = function (tuner, priority) {
	try {
		priority = priority || 0;
		fs.writeFileSync('./data/tuner.' + tuner.n + '.priority', priority, { flag: 'wx' });
		return fs.writeFileSync('./data/tuner.' + tuner.n + '.lock', process.pid, { flag: 'wx' });
	} catch (e) {
		throw e;
	}
};

exports.unlockTuner = function (tuner, callback) {
	if (fs.existsSync('./data/tuner.' + tuner.n + '.priority')) {
		fs.unlinkSync('./data/tuner.' + tuner.n + '.priority');
	}
	fs.unlink('./data/tuner.' + tuner.n + '.lock', callback);
};

exports.unlockTunerSync = function (tuner, safe) {
	try {
		if (safe === true) {
			var pid = fs.readFileSync('./data/tuner.' + tuner.n + '.lock', { encoding: 'utf8' });
			if (pid !== '') {
				if (execSync('kill -0 ' + pid) === '') {
					return null;
				} else {
					if (fs.existsSync('./data/tuner.' + tuner.n + '.priority')) {
						fs.unlinkSync('./data/tuner.' + tuner.n + '.priority');
					}
					return fs.unlinkSync('./data/tuner.' + tuner.n + '.lock');
				}
			}
		}
		if (fs.existsSync('./data/tuner.' + tuner.n + '.priority')) {
			fs.unlinkSync('./data/tuner.' + tuner.n + '.priority');
		}
		return fs.unlinkSync('./data/tuner.' + tuner.n + '.lock');
	} catch (e) {
		throw e;
	}
};

exports.writeTunerPidSync = function (tuner, pid, priority) {
	try {
		priority = priority || 0;
		fs.writeFileSync('./data/tuner.' + tuner.n + '.priority', priority, { flag: 'w' });
		return fs.writeFileSync('./data/tuner.' + tuner.n + '.lock', pid, { flag: 'w' });
	} catch (e) {
		throw e;
	}
};

var Countdown = function (count, callback) {
	this.c = count;
	this.f = callback;
};

Countdown.prototype = {
	tick: function () {

		--this.c;

		if (this.c === 0) {
			this.f();
		}

		return this;
	}
};

exports.createCountdown = function (a, b) {
	return new Countdown(a, b);
};

exports.createTimeout = function (a, b) {
	return function () {
		return setTimeout(a, b);
	};
};

exports.formatRecordedName = function (program, name) {
	name = name.replace(/<([^>]+)>/g, function (z, a) {

		// date:
		if (a.match(/^date:.+$/) !== null) { return dateFormat(new Date(program.start), a.match(/:(.+)$/)[1]); }

		// id
		if (a.match(/^id$/) !== null) { return program.id; }

		// type
		if (a.match(/^type$/) !== null) { return program.channel.type; }

		// channel
		if (a.match(/^channel$/) !== null) { return program.channel.channel; }

		// channel-id
		if (a.match(/^channel-id$/) !== null) { return program.channel.id; }

		// channel-sid
		if (a.match(/^channel-sid$/) !== null) { return program.channel.sid; }

		// channel-name
		if (a.match(/^channel-name$/) !== null) { return exports.stripFilename(program.channel.name); }

		// tuner
		if (a.match(/^tuner$/) !== null) { return program.tuner.name; }

		// title
		if (a.match(/^title$/) !== null) { return exports.stripFilename(program.title); }

		// fulltitle
		if (a.match(/^fulltitle$/) !== null) { return exports.stripFilename(program.fullTitle || ''); }

		// subtitle
		if (a.match(/^subtitle$/) !== null) { return exports.stripFilename(program.subTitle || ''); }

		// episode (zero-padded)
		if (a.match(/^episode:\d+$/) !== null) {
			var digit = a.match(/\d+/)[0];
			if (isNaN(digit)) {
				digit = 1;
			}
			return program.episode === null ? 'n' : string(program.episode.toString(10)).padLeft(digit, '0').s;
		}

		// episode
		if (a.match(/^episode$/) !== null) { return program.episode || 'n'; }

		// category
		if (a.match(/^category$/) !== null) { return program.category; }
	});

	return name;
};

// strip
exports.stripFilename = function (a) {

	a = a.replace(/\//g, '／').replace(/\\/g, '＼').replace(/:/g, '：').replace(/\*/g, '＊').replace(/\?/g, '？');
	a = a.replace(/"/g, '”').replace(/</g, '＜').replace(/>/g, '＞').replace(/\|/g, '｜').replace(/≫/g, '＞＞');

	return a;
};

// 全ルールとのマッチ判定
exports.isMatchedProgram = function (rules, program) {
	var i;
	for (i = 0; i < rules.length; i++) {
		if (exports.programMatchesRule(rules[i], program)) {
			return true;
		}
	}

	return false;
};

// 単体のルールとのマッチ判定
exports.programMatchesRule = function (rule, program) {
	var i, j, l, m, isFound;

	// isDisabled
	if (rule.isDisabled) { return false; }

	// sid
	if (rule.sid && rule.sid !== program.channel.sid) { return false; }

	// types
	if (rule.types) {
		if (rule.types.indexOf(program.channel.type) === -1) { return false; }
	}

	// channels
	if (rule.channels) {
		if (rule.channels.indexOf(program.channel.id) === -1) {
			if (rule.channels.indexOf(program.channel.channel) === -1) {
				return false;
			}
		}
	}

	// ignore_channels
	if (rule.ignore_channels) {
		if (rule.ignore_channels.indexOf(program.channel.id) !== -1) {
			return false;
		}
		if (rule.ignore_channels.indexOf(program.channel.channel) !== -1) {
			return false;
		}
	}

	// category
	if (rule.category && rule.category !== program.category) { return false; }

	// categories
	if (rule.categories) {
		if (rule.categories.indexOf(program.category) === -1) { return false; }
	}

	// hour
	if (rule.hour && (typeof rule.hour.start === 'number') && (typeof rule.hour.end === 'number') && !(rule.hour.start === 0 && rule.hour.end === 24)) {
		var ruleStart = rule.hour.start;
		var ruleEnd   = rule.hour.end;

		var progStart = new Date(program.start).getHours();
		var progEnd   = new Date(program.end).getHours();
		var progEndMinute = new Date(program.end).getMinutes();

		if (progStart > progEnd) {
			progEnd += 24;
		}
		if (progEndMinute === 0) {
			progEnd -= 1;
		}

		if (ruleStart > ruleEnd) {
			if ((ruleStart > progStart) && (ruleEnd < progEnd)) { return false; }
		} else {
			if ((ruleStart > progStart) || (ruleEnd < progEnd)) { return false; }
		}
	}

	// duration
	if (rule.duration && (typeof rule.duration.min !== 'undefined') && (typeof rule.duration.max !== 'undefined')) {
		if ((rule.duration.min > program.seconds) || (rule.duration.max < program.seconds)) { return false; }
	}

	// reserve_titles
	if (rule.reserve_titles) {
		isFound = false;

		for (i = 0; i < rule.reserve_titles.length; i++) {
			if (program.fullTitle.match(rule.reserve_titles[i]) !== null) { isFound = true; }
		}

		if (!isFound) { return false; }
	}

	// ignore_titles
	if (rule.ignore_titles) {
		for (i = 0; i < rule.ignore_titles.length; i++) {
			if (program.fullTitle.match(rule.ignore_titles[i]) !== null) { return false; }
		}
	}

	// reserve_descriptions
	if (rule.reserve_descriptions) {
		if (!program.detail) { return false; }

		isFound = false;

		for (i = 0; i < rule.reserve_descriptions.length; i++) {
			if (program.detail.match(rule.reserve_descriptions[i]) !== null) { isFound = true; }
		}

		if (!isFound) { return false; }
	}

	// ignore_descriptions
	if (rule.ignore_descriptions) {
		if (!program.detail) { return false; }

		for (i = 0; i < rule.ignore_descriptions.length; i++) {
			if (program.detail.match(rule.ignore_descriptions[i]) !== null) { return false; }
		}
	}

	// ignore_flags
	if (rule.ignore_flags) {
		for (i = 0; i < rule.ignore_flags.length; i++) {
			for (j = 0; j < program.flags.length; j++) {
				if (rule.ignore_flags[i] === program.flags[j]) { return false; }
			}
		}
	}

	// reserve_flags
	if (rule.reserve_flags) {
		if (!program.flags) { return false; }

		isFound = false;

		for (i = 0; i < rule.reserve_flags.length; i++) {
			for (j = 0; j < program.flags.length; j++) {
				if (rule.reserve_flags[i] === program.flags[j]) { isFound = true; }
			}
		}

		if (!isFound) { return false; }
	}

	return true;
};
<|endoftext|>


<commit_before>const { Gpio } = require( 'onoff' );
var socket = require('socket.io-client')('http://localhost:3000');

// set BCM 4 pin as 'output'
const in1 = new Gpio('4', 'out')
const in2  = new Gpio( '17', 'out' );
const in3 = new Gpio('27', 'out');
const in4 = new Gpio('22', 'out')

// current LED state
let isLedOn = false;

in1.writeSync(0);
in2.writeSync(0);
in3.writeSync(0);
in4.writeSync(0);

socket.on('connect', function(){
    console.log("Connected to weebo server");
});

socket.on('weebo-control', function(data){
    console.log("Received instruction:", data);
    switch (data) {
        case "l": {
            console.log("going left")
        }
        case "r": {
            console.log("going left")
        }
        case "f": {
            console.log("going forward")
        }
        case "b": {
            console.log("going backward")
        }
        default: {
            console.log("stopping")
        }
    }
});

socket.on('disconnect', function(){
    console.log("Disconnected from weebo server");
});

/*
// run a infinite interval
setInterval( () => {
  in1.writeSync( isLedOn ? 0 : 1 ); // provide 1 or 0
  isLedOn = !isLedOn; // toggle state
  console.log("LED: ", isLedOn)
}, 3000 ); // 3s
*/<commit_msg>Removing powershell code written in JS<commit_after>const { Gpio } = require( 'onoff' );
var socket = require('socket.io-client')('http://localhost:3000');

// set BCM 4 pin as 'output'
const in1 = new Gpio('4', 'out')
const in2  = new Gpio( '17', 'out' );
const in3 = new Gpio('27', 'out');
const in4 = new Gpio('22', 'out')

// current LED state
let isLedOn = false;

in1.writeSync(0);
in2.writeSync(0);
in3.writeSync(0);
in4.writeSync(0);

socket.on('connect', function(){
    console.log("Connected to weebo server");
});

socket.on('weebo-control', function(data){
    console.log("Received instruction:", data);
    switch (data) {
        case "l":
            console.log("going left")
            break;
        case "r":
            console.log("going left")
            break;
        case "f":
            console.log("going forward")
            break;
        case "b":
            console.log("going backward")
            break;
        default:
            console.log("stopping")
            break;
    }
});

socket.on('disconnect', function(){
    console.log("Disconnected from weebo server");
});

/*
// run a infinite interval
setInterval( () => {
  in1.writeSync( isLedOn ? 0 : 1 ); // provide 1 or 0
  isLedOn = !isLedOn; // toggle state
  console.log("LED: ", isLedOn)
}, 3000 ); // 3s
*/<|endoftext|>


<commit_before>define(["dojo/_base/kernel", "dojo/_base/lang", "dojo/when", "dojo/_base/array", "dojo/when" /*=====, "./api/Store" =====*/
], function(kernel, lang, when, array, when /*=====, Store =====*/){

// module:
//		dojo/store/Observable

var Observable = function(/*Store*/ store){
	// summary:
	//		The Observable store wrapper takes a store and sets an observe method on query()
	//		results that can be used to monitor results for changes.
	//
	// description:
	//		Observable wraps an existing store so that notifications can be made when a query
	//		is performed.
	//
	// example:
	//		Create a Memory store that returns an observable query, and then log some
	//		information about that query.
	//
	//	|	var store = Observable(new Memory({
	//	|		data: [
	//	|			{id: 1, name: "one", prime: false},
	//	|			{id: 2, name: "two", even: true, prime: true},
	//	|			{id: 3, name: "three", prime: true},
	//	|			{id: 4, name: "four", even: true, prime: false},
	//	|			{id: 5, name: "five", prime: true}
	//	|		]
	//	|	}));
	//	|	var changes = [], results = store.query({ prime: true });
	//	|	var observer = results.observe(function(object, previousIndex, newIndex){
	//	|		changes.push({previousIndex:previousIndex, newIndex:newIndex, object:object});
	//	|	});
	//
	//		See the Observable tests for more information.

	var undef, queryUpdaters = [], revision = 0;
	// a Comet driven store could directly call notify to notify observers when data has
	// changed on the backend
	// create a new instance
	store = lang.delegate(store);

	store.notify = function(object, existingId, methodOptions ){
		revision++;
		var updaters = queryUpdaters.slice();
		for(var i = 0, l = updaters.length; i < l; i++){
			updaters[i](object, existingId, methodOptions);
		}
	};
	var originalQuery = store.query;
	store.query = function(query, options){
		options = options || {};

		var results = originalQuery.apply(this, arguments);
		if(results && results.forEach){
			var nonPagedOptions = lang.mixin({}, options);
			delete nonPagedOptions.start;
			delete nonPagedOptions.count;

			var queryExecutor = store.queryEngine && store.queryEngine(query, nonPagedOptions);
			var queryRevision = revision;
			var listeners = [], queryUpdater;

			results.newQueryTotal = options.start + options.count;    // Added by MERC
			results.options = lang.mixin( {}, options );              // Added by MERC

			results.observe = function(listener, includeObjectUpdates){

				var newQueryTotal = results.newQueryTotal; // ADDED BY MERC
				var options = results.options;             // ADDED BY MERC

				if(listeners.push(listener) == 1){
					// first listener was added, create the query checker and updater
					queryUpdaters.push(queryUpdater = function(changed, existingId, methodOptions){
						when(results, function(resultsArray){

							var atEnd = resultsArray.length != options.count;
							var i, l, listener;
							if(++queryRevision != revision){
								throw new Error("Query is out of date, you must observe() the query prior to any data modifications");
							}

							// Look for an object with id objectId in resultsArray
							function findObjectInResult( objectId ) {
								var i, l, object;
								for(i = 0, l = resultsArray.length; i < l; i++){
									object = resultsArray[ i ];
									if( store.getIdentity( object ) == objectId ){
										return i;
									}
								}
								return -1;
							}

							// CASE #1: It's a deletion. No dramas.
							if( changed === undef && existingId !== undef ){
								var ownPosition = findObjectInResult( existingId );
								if( ownPosition != -1 ){
									newQueryTotal --;
									tellAllListeners( resultsArray[ownPosition], ownPosition, -1 );
									resultsArray.splice( ownPosition, 1 );
								}
							}

							// It's either an insert or a replace
							if( changed !== undef ){

								// Look for self in the query
								var ownPosition = findObjectInResult( existingId );

								// CASE 2: it's an update and includeObjectUpdates
								// is true: place record in-place
								if( ownPosition != -1 && includeObjectUpdates ){

									//console.log("METHOD OPTIONS:" , methodOptions, changed, existingId );

									if( methodOptions && typeof( methodOptions.before ) !== 'undefined' ){
										//console.log("MOVING THE ITEM...:" );

										//console.log("RESULTARRAY BEFORE WAS:" );
										//resultsArray.forEach( function(e, k){ console.log( k, e.name ); } );

										// methodOptions.before is null: the item needs to be at the end
                    // of the resultsArray
										if( methodOptions.before === null ){
								    	var pos = resultsArray.length;
											resultsArray.splice( ownPosition, 1 );
											resultsArray.push( changed );
											tellAllListeners( changed, ownPosition, pos -1 );
										} else {

											var beforePosition = findObjectInResult( store.getIdentity( methodOptions.before ) );
											if( beforePosition > ownPosition ) beforePosition --;

											//console.log("BEFOREPOSITION:", beforePosition, "OWNPOSITION: ", ownPosition );

											resultsArray.splice(beforePosition, 0, resultsArray.splice(ownPosition, 1)[0]);
										  tellAllListeners( changed, ownPosition, beforePosition );
										}

										// Tell all listeners...
										//console.log("RESULTARRAY NOW IS:" );
										//resultsArray.forEach( function(e, k){ console.log( k, e.name ); } );

									} else {
										resultsArray.splice( ownPosition, 1, changed );
										tellAllListeners( changed, ownPosition, ownPosition );
									}

								}

								// CASE 3: it's an add.

								if( ownPosition == -1 ){

									// There are three possibilities: it might go:
									// * first (options.placeNew === 'first'
									// * last (options.placeNew === 'last' OR options.before === null )
									// * none (options.placeNew === 'none' OR anything else )

									// CASE 3a: options.before is indeed specified.
									// In this case, look for that, and place it there
									if( methodOptions && methodOptions.before ){

										var beforePosition = findObjectInResult( store.getIdentity( methodOptions.before ) )

										if( beforePosition != -1 ){
											resultsArray.splice( beforePosition, 0, changed );
											newQueryTotal ++;
											tellAllListeners( changed, -1, beforePosition );
										}

									// CASE 3b: it's an add, and query.placeNew is "last" OR undefined
									// _OR_ options.before === null (required by store API): add the item
									// to the query marked as "last" (note: the query might not have been
									// made and therefore observed yet)
									} else if( options.placeNew === 'last' || options.placeNew === undefined ||
                    ( typeof( methodOptions ) === 'object' && methodOptions !== null && methodOptions.before === null ) ){

										// var queryTo = options.start + options.count; // var queryTo = results.ioArgs.args.headers.Range.split('-')[1];
										when( results.total ).then( function( grandTotal ) {

											// If there are no limits to the query, OR if the new element will be outside the range of
											// the current query, OR if methodOptions.before is null, add it
                      // FIXME: it should check if it's within the last page of the shown fields, so that if you are for example
                      // on page 3 of 4 and you add it last, it won't display it
											if( (options.start == 0 && options.count == 0 ) || newQueryTotal >= grandTotal || ( methodOptions && methodOptions.before === null ) ){
												var pos = resultsArray.length;
												resultsArray.push( changed );
												tellAllListeners( changed, -1, pos );
												newQueryTotal ++;
											}
										});

									// CASE 3c: it's an add, where query.placeNew is "first": will add the item
									// to the top of the list
									} else if( options.placeNew === 'first') {

										// This query has the beginning of the result: add to it
										if( options.start == 0 ){
											resultsArray.splice( 0, 0, changed );
											tellAllListeners( changed, -1, 0 );
										}

									// CASE 3d: it's an add, but query.placeNew is probably
									// "none" or undefined, do nothing
									} else{

									}

								}

							}

							function tellAllListeners( element, removedFrom, insertedInto ){
								var listener, i, copyListeners = listeners.slice();
								for(var i = 0;listener = copyListeners[i]; i++){
									listener(element, removedFrom, insertedInto );
								}
							}

/*

							var removedObject, removedFrom = -1, insertedInto = -1;
							if(existingId !== undef){
								// remove the old one
								for(i = 0, l = resultsArray.length; i < l; i++){
									var object = resultsArray[i];
									if(store.getIdentity(object) == existingId){
										removedObject = object;
										removedFrom = i;
										if(queryExecutor || !changed){// if it was changed and we don't have a queryExecutor, we shouldn't remove it because updated objects would be eliminated
											resultsArray.splice(i, 1);
										}
										break;
									}
								}
							}
							if(queryExecutor){
								// add the new one
								if(changed &&
										// if a matches function exists, use that (probably more efficient)
										(queryExecutor.matches ? queryExecutor.matches(changed) : queryExecutor([changed]).length)){

									var firstInsertedInto = removedFrom > -1 ?
										removedFrom : // put back in the original slot so it doesn't move unless it needs to (relying on a stable sort below)
										resultsArray.length;
									resultsArray.splice(firstInsertedInto, 0, changed); // add the new item
									insertedInto = array.indexOf(queryExecutor(resultsArray), changed); // sort it
									// we now need to push the chagne back into the original results array
									resultsArray.splice(firstInsertedInto, 1); // remove the inserted item from the previous index

									if((options.start && insertedInto == 0) ||
										(!atEnd && insertedInto == resultsArray.length)){
										// if it is at the end of the page, assume it goes into the prev or next page
										insertedInto = -1;
									}else{
										resultsArray.splice(insertedInto, 0, changed); // and insert into the results array with the correct index
									}
								}
							}else if(changed){
								// we don't have a queryEngine, so we can't provide any information
								// about where it was inserted or moved to. If it is an update, we leave it's position alone, other we at least indicate a new object
								if(existingId !== undef){
									// an update, keep the index the same
									insertedInto = removedFrom;
								}else if(!options.start){
									// a new object
									insertedInto = store.defaultIndex || 0;
									resultsArray.splice(insertedInto, 0, changed);
								}
							}
							if((removedFrom > -1 || insertedInto > -1) &&
									(includeObjectUpdates || !queryExecutor || (removedFrom != insertedInto))){
								var copyListeners = listeners.slice();
								for(i = 0;listener = copyListeners[i]; i++){
									listener(changed || removedObject, removedFrom, insertedInto);
								}
							}
*/

						});

					});
				}
				var handle = {};
				// TODO: Remove cancel in 2.0.
				handle.remove = handle.cancel = function(){
					// remove this listener
					var index = array.indexOf(listeners, listener);
					if(index > -1){ // check to make sure we haven't already called cancel
						listeners.splice(index, 1);
						if(!listeners.length){
							// no more listeners, remove the query updater too
							queryUpdaters.splice(array.indexOf(queryUpdaters, queryUpdater), 1);
						}
					}
				};
				return handle;
			};
		}
		return results;
	};
	var inMethod;
	function whenFinished(method, action ){
		var original = store[method];
		if(original){
			store[method] = function(value){
			var params = arguments[1];

				if(inMethod){
					// if one method calls another (like add() calling put()) we don't want two events
					return original.apply(this, arguments);
				}
				inMethod = true;
				try{
					var results = original.apply(this, arguments);
					when(results, function(results){
						action((typeof results == "object" && results) || value, params );
					});
					return results;
				}finally{
					inMethod = false;
				}
			};
		}
	}
	// monitor for updates by listening to these methods
	whenFinished("put", function(object, methodOptions ){
		store.notify(object, store.getIdentity(object), methodOptions);
	});
	whenFinished("add", function(object, methodOptions){
		store.notify(object, undefined, methodOptions);
	});
	whenFinished("remove", function(id, methodOptions){
		store.notify(undefined, id, methodOptions);
	});

	return store;
};

lang.setObject("dojo.store.Observable", Observable);

return Observable;
});
<commit_msg>Tabs fixes<commit_after>define(["dojo/_base/kernel", "dojo/_base/lang", "dojo/when", "dojo/_base/array", "dojo/when" /*=====, "./api/Store" =====*/
], function(kernel, lang, when, array, when /*=====, Store =====*/){

// module:
//		dojo/store/Observable

var Observable = function(/*Store*/ store){
	// summary:
	//		The Observable store wrapper takes a store and sets an observe method on query()
	//		results that can be used to monitor results for changes.
	//
	// description:
	//		Observable wraps an existing store so that notifications can be made when a query
	//		is performed.
	//
	// example:
	//		Create a Memory store that returns an observable query, and then log some
	//		information about that query.
	//
	//	|	var store = Observable(new Memory({
	//	|		data: [
	//	|			{id: 1, name: "one", prime: false},
	//	|			{id: 2, name: "two", even: true, prime: true},
	//	|			{id: 3, name: "three", prime: true},
	//	|			{id: 4, name: "four", even: true, prime: false},
	//	|			{id: 5, name: "five", prime: true}
	//	|		]
	//	|	}));
	//	|	var changes = [], results = store.query({ prime: true });
	//	|	var observer = results.observe(function(object, previousIndex, newIndex){
	//	|		changes.push({previousIndex:previousIndex, newIndex:newIndex, object:object});
	//	|	});
	//
	//		See the Observable tests for more information.

	var undef, queryUpdaters = [], revision = 0;
	// a Comet driven store could directly call notify to notify observers when data has
	// changed on the backend
	// create a new instance
	store = lang.delegate(store);

	store.notify = function(object, existingId, methodOptions ){
		revision++;
		var updaters = queryUpdaters.slice();
		for(var i = 0, l = updaters.length; i < l; i++){
			updaters[i](object, existingId, methodOptions);
		}
	};
	var originalQuery = store.query;
	store.query = function(query, options){
		options = options || {};

		var results = originalQuery.apply(this, arguments);
		if(results && results.forEach){
			var nonPagedOptions = lang.mixin({}, options);
			delete nonPagedOptions.start;
			delete nonPagedOptions.count;

			var queryExecutor = store.queryEngine && store.queryEngine(query, nonPagedOptions);
			var queryRevision = revision;
			var listeners = [], queryUpdater;

			results.newQueryTotal = options.start + options.count;    // Added by MERC
			results.options = lang.mixin( {}, options );              // Added by MERC

			results.observe = function(listener, includeObjectUpdates){

				var newQueryTotal = results.newQueryTotal; // ADDED BY MERC
				var options = results.options;             // ADDED BY MERC

				if(listeners.push(listener) == 1){
					// first listener was added, create the query checker and updater
					queryUpdaters.push(queryUpdater = function(changed, existingId, methodOptions){
						when(results, function(resultsArray){

							var atEnd = resultsArray.length != options.count;
							var i, l, listener;
							if(++queryRevision != revision){
								throw new Error("Query is out of date, you must observe() the query prior to any data modifications");
							}

							// Look for an object with id objectId in resultsArray
							function findObjectInResult( objectId ) {
								var i, l, object;
								for(i = 0, l = resultsArray.length; i < l; i++){
									object = resultsArray[ i ];
									if( store.getIdentity( object ) == objectId ){
										return i;
									}
								}
								return -1;
							}

							// CASE #1: It's a deletion. No dramas.
							if( changed === undef && existingId !== undef ){
								var ownPosition = findObjectInResult( existingId );
								if( ownPosition != -1 ){
									newQueryTotal --;
									tellAllListeners( resultsArray[ownPosition], ownPosition, -1 );
									resultsArray.splice( ownPosition, 1 );
								}
							}

							// It's either an insert or a replace
							if( changed !== undef ){

								// Look for self in the query
								var ownPosition = findObjectInResult( existingId );

								// CASE 2: it's an update and includeObjectUpdates
								// is true: place record in-place
								if( ownPosition != -1 && includeObjectUpdates ){

									//console.log("METHOD OPTIONS:" , methodOptions, changed, existingId );

									if( methodOptions && typeof( methodOptions.before ) !== 'undefined' ){
										//console.log("MOVING THE ITEM...:" );

										// methodOptions.before is null: the item needs to be at the end
                                        // of the resultsArray
										if( methodOptions.before === null ){
								    	    var pos = resultsArray.length;
											resultsArray.splice( ownPosition, 1 );
											resultsArray.push( changed );
											tellAllListeners( changed, ownPosition, pos -1 );
										} else {

											var beforePosition = findObjectInResult( store.getIdentity( methodOptions.before ) );
											if( beforePosition > ownPosition ) beforePosition --;

											//console.log("BEFOREPOSITION:", beforePosition, "OWNPOSITION: ", ownPosition );

											resultsArray.splice(beforePosition, 0, resultsArray.splice(ownPosition, 1)[0]);
										  tellAllListeners( changed, ownPosition, beforePosition );
										}

										// Tell all listeners...
										//console.log("RESULTARRAY NOW IS:" );
										//resultsArray.forEach( function(e, k){ console.log( k, e.name ); } );

									} else {
										resultsArray.splice( ownPosition, 1, changed );
										tellAllListeners( changed, ownPosition, ownPosition );
									}

								}

								// CASE 3: it's an add.

								if( ownPosition == -1 ){

									// There are three possibilities: it might go:
									// * first (options.placeNew === 'first'
									// * last (options.placeNew === 'last' OR options.before === null )
									// * none (options.placeNew === 'none' OR anything else )

									// CASE 3a: options.before is indeed specified.
									// In this case, look for that, and place it there
									if( methodOptions && methodOptions.before ){

										var beforePosition = findObjectInResult( store.getIdentity( methodOptions.before ) )

										if( beforePosition != -1 ){
											resultsArray.splice( beforePosition, 0, changed );
											newQueryTotal ++;
											tellAllListeners( changed, -1, beforePosition );
										}

									// CASE 3b: it's an add, and query.placeNew is "last" OR undefined
									// _OR_ options.before === null (required by store API): add the item
									// to the query marked as "last" (note: the query might not have been
									// made and therefore observed yet)
									} else if( options.placeNew === 'last' ||
										       options.placeNew === undefined ||
                                                 ( typeof( methodOptions ) === 'object' &&
                                                   methodOptions !== null &&
                                                   methodOptions.before === null
                                                  )
                                            ){

										// var queryTo = options.start + options.count; // var queryTo = results.ioArgs.args.headers.Range.split('-')[1];
										when( results.total ).then( function( grandTotal ) {

											// If there are no limits to the query, OR if the new element will
											// be outside the range of
											// the current query, OR if methodOptions.before is null, add it
                                            // FIXME: it should check if it's within the last page of
                                            // the shown fields, so that if you are for example
                                            // on page 3 of 4 and you add it last, it won't display it
											if( (options.start == 0 && options.count == 0 ) || newQueryTotal >= grandTotal || ( methodOptions && methodOptions.before === null ) ){
												var pos = resultsArray.length;
												resultsArray.push( changed );
												tellAllListeners( changed, -1, pos );
												newQueryTotal ++;
											}
										});

									// CASE 3c: it's an add, where query.placeNew is "first": will add the item
									// to the top of the list
									} else if( options.placeNew === 'first') {

										// This query has the beginning of the result: add to it
										if( options.start == 0 ){
											resultsArray.splice( 0, 0, changed );
											tellAllListeners( changed, -1, 0 );
										}

									// CASE 3d: it's an add, but query.placeNew is probably
									// "none" or undefined, do nothing
									} else{

									}

								}

							}

							function tellAllListeners( element, removedFrom, insertedInto ){
								var listener, i, copyListeners = listeners.slice();
								for(var i = 0;listener = copyListeners[i]; i++){
									listener(element, removedFrom, insertedInto );
								}
							}

/*

							var removedObject, removedFrom = -1, insertedInto = -1;
							if(existingId !== undef){
								// remove the old one
								for(i = 0, l = resultsArray.length; i < l; i++){
									var object = resultsArray[i];
									if(store.getIdentity(object) == existingId){
										removedObject = object;
										removedFrom = i;
										if(queryExecutor || !changed){// if it was changed and we don't have a queryExecutor, we shouldn't remove it because updated objects would be eliminated
											resultsArray.splice(i, 1);
										}
										break;
									}
								}
							}
							if(queryExecutor){
								// add the new one
								if(changed &&
										// if a matches function exists, use that (probably more efficient)
										(queryExecutor.matches ? queryExecutor.matches(changed) : queryExecutor([changed]).length)){

									var firstInsertedInto = removedFrom > -1 ?
										removedFrom : // put back in the original slot so it doesn't move unless it needs to (relying on a stable sort below)
										resultsArray.length;
									resultsArray.splice(firstInsertedInto, 0, changed); // add the new item
									insertedInto = array.indexOf(queryExecutor(resultsArray), changed); // sort it
									// we now need to push the chagne back into the original results array
									resultsArray.splice(firstInsertedInto, 1); // remove the inserted item from the previous index

									if((options.start && insertedInto == 0) ||
										(!atEnd && insertedInto == resultsArray.length)){
										// if it is at the end of the page, assume it goes into the prev or next page
										insertedInto = -1;
									}else{
										resultsArray.splice(insertedInto, 0, changed); // and insert into the results array with the correct index
									}
								}
							}else if(changed){
								// we don't have a queryEngine, so we can't provide any information
								// about where it was inserted or moved to. If it is an update, we leave it's position alone, other we at least indicate a new object
								if(existingId !== undef){
									// an update, keep the index the same
									insertedInto = removedFrom;
								}else if(!options.start){
									// a new object
									insertedInto = store.defaultIndex || 0;
									resultsArray.splice(insertedInto, 0, changed);
								}
							}
							if((removedFrom > -1 || insertedInto > -1) &&
									(includeObjectUpdates || !queryExecutor || (removedFrom != insertedInto))){
								var copyListeners = listeners.slice();
								for(i = 0;listener = copyListeners[i]; i++){
									listener(changed || removedObject, removedFrom, insertedInto);
								}
							}
*/

						});

					});
				}
				var handle = {};
				// TODO: Remove cancel in 2.0.
				handle.remove = handle.cancel = function(){
					// remove this listener
					var index = array.indexOf(listeners, listener);
					if(index > -1){ // check to make sure we haven't already called cancel
						listeners.splice(index, 1);
						if(!listeners.length){
							// no more listeners, remove the query updater too
							queryUpdaters.splice(array.indexOf(queryUpdaters, queryUpdater), 1);
						}
					}
				};
				return handle;
			};
		}
		return results;
	};
	var inMethod;
	function whenFinished(method, action ){
		var original = store[method];
		if(original){
			store[method] = function(value){
			var params = arguments[1];

				if(inMethod){
					// if one method calls another (like add() calling put()) we don't want two events
					return original.apply(this, arguments);
				}
				inMethod = true;
				try{
					var results = original.apply(this, arguments);
					when(results, function(results){
						action((typeof results == "object" && results) || value, params );
					});
					return results;
				}finally{
					inMethod = false;
				}
			};
		}
	}
	// monitor for updates by listening to these methods
	whenFinished("put", function(object, methodOptions ){
		store.notify(object, store.getIdentity(object), methodOptions);
	});
	whenFinished("add", function(object, methodOptions){
		store.notify(object, undefined, methodOptions);
	});
	whenFinished("remove", function(id, methodOptions){
		store.notify(undefined, id, methodOptions);
	});

	return store;
};

lang.setObject("dojo.store.Observable", Observable);

return Observable;
});
<|endoftext|>


<commit_before>/**
 * Default controller
 */

module.exports = {
  // default crud actions
  find: function(req, res, next) {
    req.context.Model.findAndCountAll()
    .done(function(err, record) {
      if (err) return res.status(500).send(err);

      var response = {};
      response[req.context.model] = record.rows;
      response.meta = {
        count: record.count
      };

      return res.status(200).send(response);
    });
  },
  create: function(req, res, next) {

    req.context.Model.create(req.body)
    .done(function(err, record) {
      if (err) return res.send(err);
      var response = {};
      response[req.context.model] = record;
      return res.status(201).send(response);
    });
  },
  findOne: function(req, res, next) {
    var id = req.params.id;

    req.context.Model.find(id)
    .done(function(err, record) {
      if (err) return res.status(500).send(err);

      var response = {};
      response[req.context.model] = record;
      return res.status(200).send(response);
    });
  },
  update: function(req, res, next) {
    var id = req.params.id;

    req.context.Model.find(id)
    .done(function(err, record) {
      if (err) return res.status(500).send(err);
      if (!record) return res.status(404).send();

      record.updateAttributes(req.body)
      .done(function(err) {
        if (err) return res.status(500).send(err);

        var response = {};
        response[req.context.model] = record;
        return res.status(200).send(response);
      });
    });
  },
  destroy: function(req, res, next) {
    var id = req.params.id;

    req.context.Model.find(id)
    .done(function(err, record) {
      if (err) return res.status(500).send(err);
      if (!record) return res.status(404).send();

      record.destroy(req.body)
      .done(function(err) {
        if (err) return res.status(500).send(err);
        return res.status(204).send();
      });
    });
  },
  // pages actions
  editPage: function(req, res, next) {
    console.log('TODO');
  },
  // atribute actions
  getAttribute: function(req, res, next) {
    console.log('TODO');
  },
  updateAttribute: function(req, res, next) {
    console.log('TODO');
  },
  deleteAttribute: function(req, res, next) {
    console.log('TODO');
  },
  // association actions
  addRecord: function(req, res, next) {
    console.log('TODO');
  },
  removeRecord: function(req, res, next) {
    console.log('TODO');
  },
  getRecord: function(req, res, next) {
    console.log('TODO');
  }
}

function parseValues(req) {
  var modelAtributes = Object.keys( we.modelsConfigs[req.context.model].definition );

}<commit_msg>update default controller to use req.getWe()<commit_after>/**
 * Default controller
 */

module.exports = {
  // default crud actions
  find: function(req, res, next) {
    req.context.Model.findAndCountAll()
    .done(function(err, record) {
      if (err) return res.status(500).send(err);

      var response = {};
      response[req.context.model] = record.rows;
      response.meta = {
        count: record.count
      };

      return res.status(200).send(response);
    });
  },
  create: function(req, res, next) {
    req.context.Model.create(req.body)
    .done(function(err, record) {
      if (err) return res.send(err);
      var response = {};
      response[req.context.model] = record;
      return res.status(201).send(response);
    });
  },
  findOne: function(req, res, next) {
    var id = req.params.id;

    req.context.Model.find(id)
    .done(function(err, record) {
      if (err) return res.status(500).send(err);

      var response = {};
      response[req.context.model] = record;
      return res.status(200).send(response);
    });
  },
  update: function(req, res, next) {
    var id = req.params.id;

    req.context.Model.find(id)
    .done(function(err, record) {
      if (err) return res.status(500).send(err);
      if (!record) return res.status(404).send();

      record.updateAttributes(req.body)
      .done(function(err) {
        if (err) return res.status(500).send(err);

        var response = {};
        response[req.context.model] = record;
        return res.status(200).send(response);
      });
    });
  },
  destroy: function(req, res, next) {
    var id = req.params.id;

    req.context.Model.find(id)
    .done(function(err, record) {
      if (err) return res.status(500).send(err);
      if (!record) return res.status(404).send();

      record.destroy(req.body)
      .done(function(err) {
        if (err) return res.status(500).send(err);
        return res.status(204).send();
      });
    });
  },
  // pages actions
  editPage: function(req, res, next) {
    console.log('TODO');
  },
  // atribute actions
  getAttribute: function(req, res, next) {
    console.log('TODO');
  },
  updateAttribute: function(req, res, next) {
    console.log('TODO');
  },
  deleteAttribute: function(req, res, next) {
    console.log('TODO');
  },
  // association actions
  addRecord: function(req, res, next) {
    console.log('TODO');
  },
  removeRecord: function(req, res, next) {
    console.log('TODO');
  },
  getRecord: function(req, res, next) {
    console.log('TODO');
  }
}

function parseValues(req) {
  var we =  req.getWe();

  var modelAtributes = Object.keys( we.modelsConfigs[req.context.model].definition );
}<|endoftext|>


<commit_before>var dataStructure = require('./dataStructure');
var service = require('./service');
var contract = require('./contract');
var dataHelp = {
    parseURL: function(sheet){
      var name = sheet.name,
          rows = sheet.data;
      var resturl = /Restful\s?URL/i,
          serverno = /Service\s?Code/i,
          urlindex = 0 ,
          servernoindex = 0,
          findurl = false,
          findserverno = false;
      var result = [];
      if(name == "Overview" && rows && rows.length){
        var title = rows[0];
        for(var i=0, len=title.length; i<len; i++){
          var t = title[i];
          if(resturl.test(t) && !findurl){
            urlindex = i;
            findurl = true;
          }
          if(serverno.test(t) && !findserverno){
            servernoindex = i;
            findserverno = true;
          }

          if(findserverno && findurl){
            break;
          }
        }

        for(j=1, l= rows.length; j<l; j++){
          var row = rows[j];
          result.push({
            serverno : row[servernoindex],
            resturl  : row[urlindex]
          });
        }
        return result;
      }
      return null;
    },

    parse : function(sheet, serverurlmap){
      var name = sheet.name;
      if(name == "Overview"){
        return ;
      }
      var reg = /(\d+)(.+)/;
      var res = reg.exec(name);
      var serverno, servername, serverresturl;
      if(res){
        serverno = res[1];
        servername = res[2];
      }
      var rows = sheet.data,
          startIndex = 1,
          requestCount = 2,
          endIndex = rows.length;
      //没有request，格式不对，直接退出
      if(!rows[startIndex][0]){
        return;
      }
      //找到response 开始的行数
      for(; requestCount<endIndex; requestCount++){
        if(rows[requestCount][0]){
          break;
        }
      }

      var request = dataStructure(sheet.data, startIndex, requestCount);
      var response = dataStructure(sheet.data, requestCount+1, endIndex);

      //获取服务对象的rest url
      if(serverurlmap && serverurlmap.length){
        serverurlmap.forEach(function(s){
          if(s.serverno == serverno){
            serverresturl = s.resturl;
            return false;
          }
        });
      }

      return {
        serverno : serverno,
        servername: servername,
        serverresturl : serverresturl,
        req : request.root,
        res : response.root
      }
    },

    save : function(data, callback){
      var msg = [];
      if(!data){
        callback && callback(msg);
        return;
      }
      service.create({name:data.servername, NO: data.serverno, url: data.serverresturl || data.serverno},
        function(err, res){
          if(err){
              //console.log(err);
              msg.push({ text: "创建service:"+data.serverno+"失败", ack:1, errmsg: err.stack });
              callback && callback(msg);
              return;
            }
            msg.push({ text: "创建service:"+data.serverno+"成功", ack:0});
            contract.create({
              srv_id : res,
              NO: data.serverno,
              req: data.req,
              res: data.res
            },function(err){
              if(err){
                  //console.log(err);
                  msg.push({ text:"创建contract:"+data.serverno+"失败", ack:1, errmsg: err.stack});
                  callback && callback(msg);
                  return;
                };
                msg.push({text: "创建contract:"+data.serverno+"成功", ack:0});
                callback && callback(msg);
            });
        });
      }
}

function iterate(datas,msg, callback){
    var data = datas.shift();
    dataHelp.save(data, function(result){
        msg = msg || [];
        msg = msg.concat(result);
        if(datas.length){
          iterate(datas, msg,callback);
        }else{
          callback && callback(msg);
        }
    });
}

// 导入契约
module.exports = function (xlsObject, callback){
    var datas = [];
    var serverurlmap = [];
    // 遍历 Sheet
    xlsObject.forEach(function(sheet, index){
        //解析overview， 提取resturl
        if(index == 0){
          serverurlmap = dataHelp.parseURL(sheet);
        }else{
          //解析具体契约，提取每个契约对象
          var data = dataHelp.parse(sheet, serverurlmap);
          if(data){
              datas.push(data);
          }
        }
    });
    iterate(datas, [], callback);
}
<commit_msg>fix bug, not save response first field<commit_after>var dataStructure = require('./dataStructure');
var service = require('./service');
var contract = require('./contract');
var dataHelp = {
    parseURL: function(sheet){
      var name = sheet.name,
          rows = sheet.data;
      var resturl = /Restful\s?URL/i,
          serverno = /Service\s?Code/i,
          urlindex = 0 ,
          servernoindex = 0,
          findurl = false,
          findserverno = false;
      var result = [];
      if(name == "Overview" && rows && rows.length){
        var title = rows[0];
        for(var i=0, len=title.length; i<len; i++){
          var t = title[i];
          if(resturl.test(t) && !findurl){
            urlindex = i;
            findurl = true;
          }
          if(serverno.test(t) && !findserverno){
            servernoindex = i;
            findserverno = true;
          }

          if(findserverno && findurl){
            break;
          }
        }

        for(j=1, l= rows.length; j<l; j++){
          var row = rows[j];
          result.push({
            serverno : row[servernoindex],
            resturl  : row[urlindex]
          });
        }
        return result;
      }
      return null;
    },

    parse : function(sheet, serverurlmap){
      var name = sheet.name;
      if(name == "Overview"){
        return ;
      }
      var reg = /(\d+)(.+)/;
      var res = reg.exec(name);
      var serverno, servername, serverresturl;
      if(res){
        serverno = res[1];
        servername = res[2];
      }
      var rows = sheet.data,
          startIndex = 1,
          requestCount = 2,
          endIndex = rows.length;
      //没有request，格式不对，直接退出
      if(!rows[startIndex][0]){
        return;
      }
      //找到response 开始的行数
      for(; requestCount<endIndex; requestCount++){
        if(rows[requestCount][0]){
          break;
        }
      }

      var request = dataStructure(sheet.data, startIndex, requestCount);
      var response = dataStructure(sheet.data, requestCount, endIndex);

      //获取服务对象的rest url
      if(serverurlmap && serverurlmap.length){
        serverurlmap.forEach(function(s){
          if(s.serverno == serverno){
            serverresturl = s.resturl;
            return false;
          }
        });
      }

      return {
        serverno : serverno,
        servername: servername,
        serverresturl : serverresturl,
        req : request.root,
        res : response.root
      }
    },

    save : function(data, callback){
      var msg = [];
      if(!data){
        callback && callback(msg);
        return;
      }
      service.create({name:data.servername, NO: data.serverno, url: data.serverresturl || data.serverno},
        function(err, res){
          if(err){
              //console.log(err);
              msg.push({ text: "创建service:"+data.serverno+"失败", ack:1, errmsg: err.stack });
              callback && callback(msg);
              return;
            }
            msg.push({ text: "创建service:"+data.serverno+"成功", ack:0});
            contract.create({
              srv_id : res,
              NO: data.serverno,
              req: data.req,
              res: data.res
            },function(err){
              if(err){
                  //console.log(err);
                  msg.push({ text:"创建contract:"+data.serverno+"失败", ack:1, errmsg: err.stack});
                  callback && callback(msg);
                  return;
                };
                msg.push({text: "创建contract:"+data.serverno+"成功", ack:0});
                callback && callback(msg);
            });
        });
      }
}

function iterate(datas,msg, callback){
    var data = datas.shift();
    dataHelp.save(data, function(result){
        msg = msg || [];
        msg = msg.concat(result);
        if(datas.length){
          iterate(datas, msg,callback);
        }else{
          callback && callback(msg);
        }
    });
}

// 导入契约
module.exports = function (xlsObject, callback){
    var datas = [];
    var serverurlmap = [];
    // 遍历 Sheet
    xlsObject.forEach(function(sheet, index){
        //解析overview， 提取resturl
        if(index == 0){
          serverurlmap = dataHelp.parseURL(sheet);
        }else{
          //解析具体契约，提取每个契约对象
          var data = dataHelp.parse(sheet, serverurlmap);
          if(data){
              datas.push(data);
          }
        }
    });
    iterate(datas, [], callback);
}
<|endoftext|>