<commit_before>const itk = {}

import extensionToImageIO from './extensionToImageIO'
itk.extensionToImageIO = extensionToImageIO

import extensionToMeshIO from './extensionToMeshIO.js'
itk.extensionToMeshIO = extensionToMeshIO

import FloatTypes from './FloatTypes.js'
itk.FloatTypes = FloatTypes

import getFileExtension from './getFileExtension.js'
itk.getFileExtension = getFileExtension

import getMatrixElement from './getMatrixElement.js'
itk.getMatrixElement = getMatrixElement

import imageIOComponentToJSComponent from './imageIOComponentToJSComponent.js'
itk.imageIOComponentToJSComponent = imageIOComponentToJSComponent

import ImageIOIndex from './ImageIOIndex.js'
itk.ImageIOIndex = ImageIOIndex

import imageIOPixelTypeToJSPixelType from './imageIOPixelTypeToJSPixelType.js'
itk.imageIOPixelTypeToJSPixelType = imageIOPixelTypeToJSPixelType

import Image from './Image.js'
itk.Image = Image

import imageJSComponentToIOComponent from './imageJSComponentToIOComponent.js'
itk.imageJSComponentToIOComponent = imageJSComponentToIOComponent

import imageJSPixelTypeToIOPixelType from './imageJSPixelTypeToIOPixelType.js'
itk.imageJSPixelTypeToIOPixelType = imageJSPixelTypeToIOPixelType

import ImageType from './ImageType.js'
itk.ImageType = ImageType

import IntTypes from './IntTypes.js'
itk.IntTypes = IntTypes

import IOTypes from './IOTypes.js'
itk.IOTypes = IOTypes

import Matrix from './Matrix.js'
itk.Matrix = Matrix

import meshIOComponentToJSComponent from './meshIOComponentToJSComponent.js'
itk.meshIOComponentToJSComponent = meshIOComponentToJSComponent

import MeshIOIndex from './MeshIOIndex.js'
itk.MeshIOIndex = MeshIOIndex

import meshIOPixelTypeToJSPixelType from './meshIOPixelTypeToJSPixelType.js'
itk.meshIOPixelTypeToJSPixelType = meshIOPixelTypeToJSPixelType

import Mesh from './Mesh.js'
itk.Mesh = Mesh

import meshJSComponentToIOComponent from './meshJSComponentToIOComponent.js'
itk.meshJSComponentToIOComponent = meshJSComponentToIOComponent

import meshJSPixelTypeToIOPixelType from './meshJSPixelTypeToIOPixelType.js'
itk.meshJSPixelTypeToIOPixelType = meshJSPixelTypeToIOPixelType

import MeshType from './MeshType.js'
itk.MeshType = MeshType

import MimeToImageIO from './MimeToImageIO.js'
itk.MimeToImageIO = MimeToImageIO

import MimeToMeshIO from './MimeToMeshIO.js'
itk.MimeToMeshIO = MimeToMeshIO

import PixelTypes from './PixelTypes.js'
itk.PixelTypes = PixelTypes

import readImageArrayBuffer from './readImageArrayBuffer.js'
itk.readImageArrayBuffer = readImageArrayBuffer

import readImageBlob from './readImageBlob.js'
itk.readImageBlob = readImageBlob

import readImageDICOMFileSeries from './readImageDICOMFileSeries.js'
itk.readImageDICOMFileSeries = readImageDICOMFileSeries

import readImageFile from './readImageFile.js'
itk.readImageFile = readImageFile

import readLocalFile from './readLocalFile.js'
itk.readLocalFile = readLocalFile

import readMeshArrayBuffer from './readMeshArrayBuffer.js'
itk.readMeshArrayBuffer = readMeshArrayBuffer

import readMeshBlob from './readMeshBlob.js'
itk.readMeshBlob = readMeshBlob

import readMeshFile from './readMeshFile.js'
itk.readMeshFile = readMeshFile

import runPipelineBrowser from './runPipelineBrowser.js'
itk.runPipelineBrowser = runPipelineBrowser

import setMatrixElement from './setMatrixElement.js'
itk.setMatrixElement = setMatrixElement

import writeImageArrayBuffer from './writeImageArrayBuffer.js'
itk.writeImageArrayBuffer = writeImageArrayBuffer

import writeMeshArrayBuffer from './writeMeshArrayBuffer.js'
itk.writeMeshArrayBuffer = writeMeshArrayBuffer

// Expose itk to global scope without exporting it so nested namespace
// do not pollute the global one.
window.itk = itk
<commit_msg>fix(index): Remove readLocalFile<commit_after>const itk = {}

import extensionToImageIO from './extensionToImageIO'
itk.extensionToImageIO = extensionToImageIO

import extensionToMeshIO from './extensionToMeshIO.js'
itk.extensionToMeshIO = extensionToMeshIO

import FloatTypes from './FloatTypes.js'
itk.FloatTypes = FloatTypes

import getFileExtension from './getFileExtension.js'
itk.getFileExtension = getFileExtension

import getMatrixElement from './getMatrixElement.js'
itk.getMatrixElement = getMatrixElement

import imageIOComponentToJSComponent from './imageIOComponentToJSComponent.js'
itk.imageIOComponentToJSComponent = imageIOComponentToJSComponent

import ImageIOIndex from './ImageIOIndex.js'
itk.ImageIOIndex = ImageIOIndex

import imageIOPixelTypeToJSPixelType from './imageIOPixelTypeToJSPixelType.js'
itk.imageIOPixelTypeToJSPixelType = imageIOPixelTypeToJSPixelType

import Image from './Image.js'
itk.Image = Image

import imageJSComponentToIOComponent from './imageJSComponentToIOComponent.js'
itk.imageJSComponentToIOComponent = imageJSComponentToIOComponent

import imageJSPixelTypeToIOPixelType from './imageJSPixelTypeToIOPixelType.js'
itk.imageJSPixelTypeToIOPixelType = imageJSPixelTypeToIOPixelType

import ImageType from './ImageType.js'
itk.ImageType = ImageType

import IntTypes from './IntTypes.js'
itk.IntTypes = IntTypes

import IOTypes from './IOTypes.js'
itk.IOTypes = IOTypes

import Matrix from './Matrix.js'
itk.Matrix = Matrix

import meshIOComponentToJSComponent from './meshIOComponentToJSComponent.js'
itk.meshIOComponentToJSComponent = meshIOComponentToJSComponent

import MeshIOIndex from './MeshIOIndex.js'
itk.MeshIOIndex = MeshIOIndex

import meshIOPixelTypeToJSPixelType from './meshIOPixelTypeToJSPixelType.js'
itk.meshIOPixelTypeToJSPixelType = meshIOPixelTypeToJSPixelType

import Mesh from './Mesh.js'
itk.Mesh = Mesh

import meshJSComponentToIOComponent from './meshJSComponentToIOComponent.js'
itk.meshJSComponentToIOComponent = meshJSComponentToIOComponent

import meshJSPixelTypeToIOPixelType from './meshJSPixelTypeToIOPixelType.js'
itk.meshJSPixelTypeToIOPixelType = meshJSPixelTypeToIOPixelType

import MeshType from './MeshType.js'
itk.MeshType = MeshType

import MimeToImageIO from './MimeToImageIO.js'
itk.MimeToImageIO = MimeToImageIO

import MimeToMeshIO from './MimeToMeshIO.js'
itk.MimeToMeshIO = MimeToMeshIO

import PixelTypes from './PixelTypes.js'
itk.PixelTypes = PixelTypes

import readImageArrayBuffer from './readImageArrayBuffer.js'
itk.readImageArrayBuffer = readImageArrayBuffer

import readImageBlob from './readImageBlob.js'
itk.readImageBlob = readImageBlob

import readImageDICOMFileSeries from './readImageDICOMFileSeries.js'
itk.readImageDICOMFileSeries = readImageDICOMFileSeries

import readImageFile from './readImageFile.js'
itk.readImageFile = readImageFile

import readMeshArrayBuffer from './readMeshArrayBuffer.js'
itk.readMeshArrayBuffer = readMeshArrayBuffer

import readMeshBlob from './readMeshBlob.js'
itk.readMeshBlob = readMeshBlob

import readMeshFile from './readMeshFile.js'
itk.readMeshFile = readMeshFile

import runPipelineBrowser from './runPipelineBrowser.js'
itk.runPipelineBrowser = runPipelineBrowser

import setMatrixElement from './setMatrixElement.js'
itk.setMatrixElement = setMatrixElement

import writeImageArrayBuffer from './writeImageArrayBuffer.js'
itk.writeImageArrayBuffer = writeImageArrayBuffer

import writeMeshArrayBuffer from './writeMeshArrayBuffer.js'
itk.writeMeshArrayBuffer = writeMeshArrayBuffer

// Expose itk to global scope without exporting it so nested namespace
// do not pollute the global one.
window.itk = itk
<|endoftext|>


<commit_before>const isValidString =
  param =>
    typeof param === 'string' && param.length > 0;

const startsWith =
  (string, start) =>
    string.indexOf(start) === 0;

const isSelector =
  param =>
    isValidString(param) && ( startsWith(param, '.') || startsWith(param, '#') );

const node =
  h =>
    tagName =>
      (first, ...rest) => {
        if (isSelector(first)) {
          return h(tagName + first, ...rest);
        } else {
          return h(tagName, first, ...rest);
        }
      };

const TAG_NAMES =
  [
  'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base',
  'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption',
  'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl',
  'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
  'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html',
  'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend',
  'li', 'link', 'map', 'mark', 'menu', 'meta', 'nav', 'noscript', 'object',
  'ol', 'optgroup', 'option', 'p', 'param', 'pre', 'q', 'rp', 'rt', 'ruby', 's',
  'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong',
  'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th',
  'thead', 'title', 'tr', 'u', 'ul', 'video'
  ];

module.exports =
  h => {
    const exported = {};
    const genericnode = node(h);
    TAG_NAMES.forEach(n => {
        exported[n] = genericnode(n);
    });
    exported.TAG_NAMES = TAG_NAMES;
    exported.isSelector = isSelector;
    return exported;
  };
<commit_msg>combine TAG_NAMES and isSelector into literal<commit_after>const isValidString =
  param =>
    typeof param === 'string' && param.length > 0;

const startsWith =
  (string, start) =>
    string.indexOf(start) === 0;

const isSelector =
  param =>
    isValidString(param) && ( startsWith(param, '.') || startsWith(param, '#') );

const node =
  h =>
    tagName =>
      (first, ...rest) => {
        if (isSelector(first)) {
          return h(tagName + first, ...rest);
        } else {
          return h(tagName, first, ...rest);
        }
      };

const TAG_NAMES =
  [
  'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base',
  'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption',
  'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dir', 'div', 'dl',
  'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form',
  'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html',
  'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'keygen', 'label', 'legend',
  'li', 'link', 'map', 'mark', 'menu', 'meta', 'nav', 'noscript', 'object',
  'ol', 'optgroup', 'option', 'p', 'param', 'pre', 'q', 'rp', 'rt', 'ruby', 's',
  'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong',
  'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th',
  'thead', 'title', 'tr', 'u', 'ul', 'video'
  ];

module.exports =
  h => {
    const exported = { TAG_NAMES, isSelector };
    const genericnode = node(h);
    TAG_NAMES.forEach(n => {
        exported[n] = genericnode(n);
    });
    return exported;
  };
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const AWS = require('aws-sdk');

const logger = require('log4js').getLogger();

const argv = yargs
	.alias('s', 'server').describe('server', 'The address and port of the Kubernetes API server')
	.alias('cacert', 'certificate-authority').describe('certificate-authority', 'Path to a cert. file for the certificate authority')
	.alias('cert', 'client-certificate').describe('client-certificate', 'Path to a client certificate file for TLS')
	.alias('key', 'client-key').describe('client-key', 'Path to a client key file for TLS')
	.boolean('insecure-skip-tls-verify').describe('insecure-skip-tls-verify', 'If true, the server\'s certificate will not be checked for validity. This will make your HTTPS connections insecure')
	.describe('token', 'Bearer token for authentication to the API server')
	.describe('namespace', 'The namespace to watch')
	.help()
	.argv;

/** The basic configuration for accessing the API server */
let k8sConfig;
if (argv.server) {
	const fs = require('fs');

	k8sConfig = {
		url: argv.server,
		insecureSkipTlsVerify: argv.insecureSkipTlsVerify
	};
	if (argv.certificateAuthority) {
		k8sConfig.ca = fs.readFileSync(argv.certificateAuthority, 'utf8');
	}
	if (argv.token) {
		k8sConfig.auth = { bearer: argv.token };
	} else if (argv.username && argv.password) {
		k8sConfig.auth = { user: argv.username, pass: argv.password };
	} else if (argv.clientCertificate && argv.clientKey) {
		k8sConfig.cert = fs.readFileSync(argv.clientCertificate, 'utf8');
		k8sConfig.key = fs.readFileSync(argv.clientKey, 'utf8');
	}
} else if (process.env.KUBERNETES_SERVICE_HOST) {
	const credentialsPath = '/var/run/secrets/kubernetes.io/serviceaccount/';
	k8sConfig = {
		url: `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`,
		ca: fs.readFileSync(path.resolve(credentialsPath, 'ca.crt'), 'utf8'),
		auth: { bearer: fs.readFileSync(path.resolve(credentialsPath, 'token'), 'utf8') }
	}
} else {
	logger.error('Unknown Kubernetes API server');
	process.exit(1);
}

const k8s = require('auto-kubernetes-client');
const sqs = new AWS.SQS({
	endpoint: process.env.AWS_SQS_ENDPOINT_URL_OVERRIDE,
	region: process.env.AWS_REGION,
});

if (!argv.namespace) {
	// FIXME: How to do watching without namespace (i.e. "all namespaces")
	logger.error('Must provide a namespace using --namespace');
	process.exit(1);
}

k8s(k8sConfig).then(function(k8sClient) {
	/**
	 * Convert the queue.spec parts from camelCase to AWS CapitalCase.
	 *
	 * @param {Object} queue a queue definition
	 * @param {String} [queueArn] the ARN of the queue
	 * @return {Object} the queue attributes
	 */
	function translateQueueAttributes(queue, queueArn) {
		function capitalize(s) {
			return s[0].toUpperCase() + s.substring(1);
		}

		return Object.keys(queue.spec || {}).reduce((result, key) => {
			const value = queue.spec[key];
			let resultValue;
			switch (key) {
			case 'redrivePolicy':
				resultValue = JSON.stringify(value);
				break;
			case 'policy':
				// Inject the queue ARN as 'Resource' into all statements of the policy
				let policy;
				if (queueArn) {
					logger.debug(`[${queue.metadata.name}]: Injecting resource ARN ${queueArn} into policy document`)
					policy = Object.assign({}, value, { Statement: (value.Statement || []).map(statement => Object.assign({Resource: queueArn}, statement)) });
				} else {
					policy = value;
				}

				resultValue = JSON.stringify(policy);
				break;
			default:
				// Convert to string
				resultValue = `${value}`;
				break;
			}
			logger.debug(`[${queue.metadata.name}]: Attribute ${key} = ${resultValue}`);

			result[capitalize(key)] = resultValue;
			return result;
		}, {});
	}

	function createQueue(queue) {
		return new Promise(function(resolve, reject) {
			function handleCreateQueueResponse(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.QueueDeletedRecently') {
						// Schedule to retry the operation in 10s
						logger.info(`[${queue.metadata.name}]: Retrying for recently deleted queue`);
						return setTimeout(function() {
							return createQueue(queue).then(data => handleCreateQueueResponse(null, data), err => handleCreateQueueResponse(err, null));
						}, 10000);
					}
					logger.warn(`[${queue.metadata.name}]: Cannot create queue: ${err.message}`);
					return reject(err);
				}

				return resolve(data);
			}

			const attributes = translateQueueAttributes(queue);
			return sqs.createQueue({ QueueName: queue.metadata.name, Attributes: attributes }, handleCreateQueueResponse);
		});
	}

	function updateQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.NonExistentQueue') {
						// Queue doesn't exist: this means kubernetes saw an update, but in fact the queue was never created,
						// or has been deleted in the meantime. Create it again.
						logger.info(`[${queue.metadata.name}]: Queue does not/no longer exist, re-creating it`);
						return resolve(createQueue(queue));
					}

					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				const queueUrl = data.QueueUrl;
				return sqs.getQueueAttributes({ QueueUrl: queueUrl, AttributeNames: [ 'QueueArn' ] }, function(err, data) {
					if (err) {
						logger.warn(`[${queue.metadata.name}]: Cannot determine queue ARN: ${err.message}`);
						return reject(err);
					}

					const attributes = translateQueueAttributes(queue, data.Attributes.QueueArn);
					if (Object.keys(attributes).length === 0) {
						// The API requires that we provide attributes when trying to update attributes.
						// If the caller intended to set values to their defaults, then they must be explicit and
						// provide these values. In other words: AWS SQS copies the defaults at creation time, and
						// afterwards there is no such thing as a "default" anymore.
						// From our side though this is not an error, but we merely ignore the request.
						// See also a similar change in Apache Camel: https://issues.apache.org/jira/browse/CAMEL-5782
						logger.warn(`[${queue.metadata.name}]: Ignoring update without attributes`);
						return resolve();
					}

					return sqs.setQueueAttributes({ QueueUrl: queueUrl, Attributes: attributes }, function(err, data) {
						if (err) {
							logger.warn(`[${queue.metadata.name}]: Cannot update queue attributes: ${err.message}`);
							return reject(err);
						}

						return resolve(data);
					});
				});
			});
		});
	}

	function deleteQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				return sqs.deleteQueue({ QueueUrl: data.QueueUrl }, function(err, data) {
					if (err) {
						logger.warn(`[${queue.metadata.name}]: Cannot delete queue: ${err.message}`);
						return reject(err);
					}

					return resolve(data);
				});
			});
		});
	}

	const queues = k8sClient.group('aws.k8s.collaborne.com', 'v1').ns(argv.namespace).queues;

	function mainLoop() {
		// Highest version seen
		let resourceVersion = 0;

		// Known promises for queues, used to synchronize requests and avoid races between delayed creations and modifications.
		const queuePromises = {};

		logger.info(`Watching queues at ${resourceVersion}...`);
		queues.watch(resourceVersion)
			.on('data', function(item) {
				const queue = item.object;

				// Update the version: we've processed things until here now
				resourceVersion = queue.metadata.resourceVersion;
				const name = queue.metadata.name;

				// Enqueue the request to happen when the previous request is done.
				const previousPromise = queuePromises[name] || Promise.resolve();

				let result;

				switch (item.type) {
				case 'ADDED':
					result = previousPromise.then(function() {
						logger.info(`[${name}]: Creating queue`);
						return createQueue(queue);
					});
					break;
				case 'MODIFIED':
					result = previousPromise.then(function() {
						logger.info(`[${name}]: Updating queue attributes`);
						return updateQueue(queue);
					});
					break;
				case 'DELETED':
					result = previousPromise.then(function() {
						logger.info(`[${name}]: Deleting queue`);
						return deleteQueue(queue);
					});
					break;
				case 'ERROR':
					// Log the message, and continue: usually the stream would end now, but there might be more events
					// in it that we do want to consume.
					logger.warn(`Error while watching: ${item.object.message}, ignoring`);
					return;
				default:
					logger.warn(`Unkown watch event type ${item.type}, ignoring`);
					return;
				}

				result = result.then(function(data) {
					logger.info(`[${name}]: ${JSON.stringify(data)}`);
				}, function(err) {
					logger.error(`[${name}]: ${err.message} (${err.code})`);
				});

				// Note that we retain the 'rejected' state here: an existing queue that ended in a rejection
				// will effectively stay rejected.
				queuePromises[name] = result;

				return result;
			})
			.on('end', function() {
				// Restart the whole thing.
				logger.info('Watch ended, re-syncing everything');
				return mainLoop();
			});
	}

	// Start!
	mainLoop();
}).catch(function(err) {
	logger.error(`Uncaught error, aborting: ${err.message}`);
	process.exit(1);
});
<commit_msg>Retain the promises even when a watch ends<commit_after>#!/usr/bin/env node

'use strict';

const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const AWS = require('aws-sdk');

const logger = require('log4js').getLogger();

const argv = yargs
	.alias('s', 'server').describe('server', 'The address and port of the Kubernetes API server')
	.alias('cacert', 'certificate-authority').describe('certificate-authority', 'Path to a cert. file for the certificate authority')
	.alias('cert', 'client-certificate').describe('client-certificate', 'Path to a client certificate file for TLS')
	.alias('key', 'client-key').describe('client-key', 'Path to a client key file for TLS')
	.boolean('insecure-skip-tls-verify').describe('insecure-skip-tls-verify', 'If true, the server\'s certificate will not be checked for validity. This will make your HTTPS connections insecure')
	.describe('token', 'Bearer token for authentication to the API server')
	.describe('namespace', 'The namespace to watch')
	.help()
	.argv;

/** The basic configuration for accessing the API server */
let k8sConfig;
if (argv.server) {
	const fs = require('fs');

	k8sConfig = {
		url: argv.server,
		insecureSkipTlsVerify: argv.insecureSkipTlsVerify
	};
	if (argv.certificateAuthority) {
		k8sConfig.ca = fs.readFileSync(argv.certificateAuthority, 'utf8');
	}
	if (argv.token) {
		k8sConfig.auth = { bearer: argv.token };
	} else if (argv.username && argv.password) {
		k8sConfig.auth = { user: argv.username, pass: argv.password };
	} else if (argv.clientCertificate && argv.clientKey) {
		k8sConfig.cert = fs.readFileSync(argv.clientCertificate, 'utf8');
		k8sConfig.key = fs.readFileSync(argv.clientKey, 'utf8');
	}
} else if (process.env.KUBERNETES_SERVICE_HOST) {
	const credentialsPath = '/var/run/secrets/kubernetes.io/serviceaccount/';
	k8sConfig = {
		url: `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`,
		ca: fs.readFileSync(path.resolve(credentialsPath, 'ca.crt'), 'utf8'),
		auth: { bearer: fs.readFileSync(path.resolve(credentialsPath, 'token'), 'utf8') }
	}
} else {
	logger.error('Unknown Kubernetes API server');
	process.exit(1);
}

const k8s = require('auto-kubernetes-client');
const sqs = new AWS.SQS({
	endpoint: process.env.AWS_SQS_ENDPOINT_URL_OVERRIDE,
	region: process.env.AWS_REGION,
});

if (!argv.namespace) {
	// FIXME: How to do watching without namespace (i.e. "all namespaces")
	logger.error('Must provide a namespace using --namespace');
	process.exit(1);
}

k8s(k8sConfig).then(function(k8sClient) {
	/**
	 * Convert the queue.spec parts from camelCase to AWS CapitalCase.
	 *
	 * @param {Object} queue a queue definition
	 * @param {String} [queueArn] the ARN of the queue
	 * @return {Object} the queue attributes
	 */
	function translateQueueAttributes(queue, queueArn) {
		function capitalize(s) {
			return s[0].toUpperCase() + s.substring(1);
		}

		return Object.keys(queue.spec || {}).reduce((result, key) => {
			const value = queue.spec[key];
			let resultValue;
			switch (key) {
			case 'redrivePolicy':
				resultValue = JSON.stringify(value);
				break;
			case 'policy':
				// Inject the queue ARN as 'Resource' into all statements of the policy
				let policy;
				if (queueArn) {
					logger.debug(`[${queue.metadata.name}]: Injecting resource ARN ${queueArn} into policy document`)
					policy = Object.assign({}, value, { Statement: (value.Statement || []).map(statement => Object.assign({Resource: queueArn}, statement)) });
				} else {
					policy = value;
				}

				resultValue = JSON.stringify(policy);
				break;
			default:
				// Convert to string
				resultValue = `${value}`;
				break;
			}
			logger.debug(`[${queue.metadata.name}]: Attribute ${key} = ${resultValue}`);

			result[capitalize(key)] = resultValue;
			return result;
		}, {});
	}

	function createQueue(queue) {
		return new Promise(function(resolve, reject) {
			function handleCreateQueueResponse(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.QueueDeletedRecently') {
						// Schedule to retry the operation in 10s
						logger.info(`[${queue.metadata.name}]: Retrying for recently deleted queue`);
						return setTimeout(function() {
							return createQueue(queue).then(data => handleCreateQueueResponse(null, data), err => handleCreateQueueResponse(err, null));
						}, 10000);
					}
					logger.warn(`[${queue.metadata.name}]: Cannot create queue: ${err.message}`);
					return reject(err);
				}

				return resolve(data);
			}

			const attributes = translateQueueAttributes(queue);
			return sqs.createQueue({ QueueName: queue.metadata.name, Attributes: attributes }, handleCreateQueueResponse);
		});
	}

	function updateQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.NonExistentQueue') {
						// Queue doesn't exist: this means kubernetes saw an update, but in fact the queue was never created,
						// or has been deleted in the meantime. Create it again.
						logger.info(`[${queue.metadata.name}]: Queue does not/no longer exist, re-creating it`);
						return resolve(createQueue(queue));
					}

					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				const queueUrl = data.QueueUrl;
				return sqs.getQueueAttributes({ QueueUrl: queueUrl, AttributeNames: [ 'QueueArn' ] }, function(err, data) {
					if (err) {
						logger.warn(`[${queue.metadata.name}]: Cannot determine queue ARN: ${err.message}`);
						return reject(err);
					}

					const attributes = translateQueueAttributes(queue, data.Attributes.QueueArn);
					if (Object.keys(attributes).length === 0) {
						// The API requires that we provide attributes when trying to update attributes.
						// If the caller intended to set values to their defaults, then they must be explicit and
						// provide these values. In other words: AWS SQS copies the defaults at creation time, and
						// afterwards there is no such thing as a "default" anymore.
						// From our side though this is not an error, but we merely ignore the request.
						// See also a similar change in Apache Camel: https://issues.apache.org/jira/browse/CAMEL-5782
						logger.warn(`[${queue.metadata.name}]: Ignoring update without attributes`);
						return resolve();
					}

					return sqs.setQueueAttributes({ QueueUrl: queueUrl, Attributes: attributes }, function(err, data) {
						if (err) {
							logger.warn(`[${queue.metadata.name}]: Cannot update queue attributes: ${err.message}`);
							return reject(err);
						}

						return resolve(data);
					});
				});
			});
		});
	}

	function deleteQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				return sqs.deleteQueue({ QueueUrl: data.QueueUrl }, function(err, data) {
					if (err) {
						logger.warn(`[${queue.metadata.name}]: Cannot delete queue: ${err.message}`);
						return reject(err);
					}

					return resolve(data);
				});
			});
		});
	}

	const queues = k8sClient.group('aws.k8s.collaborne.com', 'v1').ns(argv.namespace).queues;
	// Known promises for queues, used to synchronize requests and avoid races between delayed creations and modifications.
	const queuePromises = {};

	function mainLoop() {
		// Highest version seen
		let resourceVersion = 0;

		logger.info(`Watching queues at ${resourceVersion}...`);
		queues.watch(resourceVersion)
			.on('data', function(item) {
				const queue = item.object;

				// Update the version: we've processed things until here now
				resourceVersion = queue.metadata.resourceVersion;
				const name = queue.metadata.name;

				// Enqueue the request to happen when the previous request is done.
				const previousPromise = queuePromises[name] || Promise.resolve();

				let result;

				switch (item.type) {
				case 'ADDED':
					result = previousPromise.then(function() {
						logger.info(`[${name}]: Creating queue`);
						return createQueue(queue);
					});
					break;
				case 'MODIFIED':
					result = previousPromise.then(function() {
						logger.info(`[${name}]: Updating queue attributes`);
						return updateQueue(queue);
					});
					break;
				case 'DELETED':
					result = previousPromise.then(function() {
						logger.info(`[${name}]: Deleting queue`);
						return deleteQueue(queue);
					});
					break;
				case 'ERROR':
					// Log the message, and continue: usually the stream would end now, but there might be more events
					// in it that we do want to consume.
					logger.warn(`Error while watching: ${item.object.message}, ignoring`);
					return;
				default:
					logger.warn(`Unkown watch event type ${item.type}, ignoring`);
					return;
				}

				result = result.then(function(data) {
					logger.info(`[${name}]: ${JSON.stringify(data)}`);
				}, function(err) {
					logger.error(`[${name}]: ${err.message} (${err.code})`);
				});

				// Note that we retain the 'rejected' state here: an existing queue that ended in a rejection
				// will effectively stay rejected.
				queuePromises[name] = result;

				return result;
			})
			.on('end', function() {
				// Restart the whole thing.
				logger.info('Watch ended, re-syncing everything');
				return mainLoop();
			});
	}

	// Start!
	mainLoop();
}).catch(function(err) {
	logger.error(`Uncaught error, aborting: ${err.message}`);
	process.exit(1);
});
<|endoftext|>


<commit_before>'use strict';

const emailClientOnAdminVacancyRemoval = require('../utils/mailgun.js').emailClientOnAdminVacancyRemoval;
const emailAgencyForAdminAcceptance    = require('../utils/app.js').emailAgencyForAdminAcceptance;
const emailClientAboutNewCandidates    = require('../utils/app.js').emailClientAboutNewCandidates;
const emailAgencyForAdminRejection     = require('../utils/mailgun.js').emailAgencyForAdminRejection;
const getSetMembersInfo                = require('../../db/redis.js').getSetMembersInfo;
const getVacancyDetails                = require('../../db/redis.js').getVacancyDetails;
const removeVacancy                    = require('../../db/redis.js').removeVacancy;
const adminApproveCV                   = require('../../db/redis.js').adminApproveCV;
const removeCV                         = require('../../db/redis.js').removeCV;

const client  = require('../../db/client.js');
const mailgun = require('../utils/mailgun.js');
const layout  = { layout: 'admin' };

exports.register = (server, options, next) => {

    server.route([{
        method: 'GET',
        path: '/admin/job/{vid}',
        config: {
            auth: {
                strategy: 'hrns-cookie',
                scope: 'admin'
            },
            handler: (request, reply) => {
                let vid = request.params.vid;
                let opts = { title: 'Job page', vid: vid };

                getVacancyDetails(vid, (res) => {
                  if (res) {
                    opts.clientEmail = res.clientEmail;
                    opts.data = res;
                    let shortlist = vid + 'adminShortlist';

                    getSetMembersInfo(shortlist, (res) => {
                        if (res) {
                          opts.cvs = res;
                        } else {
                          opts.message ='There are no candidates for you to approve at the moment... come back when there are!';
                        }
                        reply.view('adminjob', opts, layout);
                    });
                  } else { // test this else block
                    opts.message = 'Sorry, something went wrong, please try again';
                    return reply.view('message', opts, layout);
                  }
                });
            }
        }
    }, {
        method: 'GET',
        path: '/admin/job/remove/{vid}',
        config: {
            auth: {
                strategy: 'hrns-cookie',
                scope: 'admin'
            },
            handler: (request, reply) => {
                let opts = { title: 'Sorry...', message: 'Something went wrong, please go back and try again' };
                let vid = request.params.vid;

                getVacancyDetails(vid, (res) => {
                    if (res) {
                      let clientEmail  = res.clientEmail;
                      let clientId     = res.clientId;
                      let jobTitle     = res.jobTitle;
                      opts.clientEmail = clientEmail;

                      emailClientOnAdminVacancyRemoval.to   = clientEmail;
                      emailClientOnAdminVacancyRemoval.html = emailClientOnAdminVacancyRemoval.html.replace('-jobTitle-', jobTitle);
                      mailgun.messages().send(emailClientOnAdminVacancyRemoval);

                      removeVacancy(vid, clientId, (res) => {
                          if (res) {
                              opts.title = 'Removal successful!';
                              opts.message = 'You have successfully removed this vacancy... Return home';
                              reply.view('message', opts, layout);
                          }
                      });
                    } else {
                        reply.view('message', opts, layout);
                    }
                });
            }
        }
    }, {
      method: 'GET',
      path: '/admin/job/reject',
      config: {
          auth: {
              strategy: 'hrns-cookie',
              scope: 'admin'
          },
          handler: (request, reply) => {
            let agencyEmail = request.query.agencyEmail;
            let cvid        = request.query.cvid;
            let vid         = request.query.vid;
            let set         = vid + 'adminShortlist';

            emailAgencyForAdminRejection.to = agencyEmail;

            client.hget(cvid, 'candidateName', (err, res) => {
              if (res) {
                let candidateName = res;
                client.hgetall(vid, (err, res) => {
                  if (res) {
                    let companyName = res.companyName;
                    let jobTitle    = res.jobTitle;

                    emailAgencyForAdminRejection.html = emailAgencyForAdminRejection.html.replace('-candidateName-', candidateName).replace('-jobTitle-', jobTitle).replace('-companyName-', companyName);
                    mailgun.messages().send(emailAgencyForAdminRejection);

                    removeCV(cvid, set, (res) => {
                          if (res) {
                            reply(true);
                          } else {
                            reply(false);
                          }
                      });
                  } else {
                    reply(false);
                  }
                });
              } else {
                reply(false);
              }
            });
          }
        }
    }, {
      method: 'GET',
      path: '/rating/',
      config: {
          auth: {
              strategy: 'hrns-cookie',
              scope: 'admin'
          },
          handler: (request, reply) => {
              let vid         = request.query.vid;
              let rating      = request.query.rating;
              let agencyEmail = request.query.agencyEmail;
              let cvid        = request.query.cvid;
              let message = 'Something went wrong... please try again';

               adminApproveCV(cvid, vid, rating, (res) => {
                        if (res) {
                          reply(cvid);
                        } else {
                           reply(message);
                        }
               });

              emailAgencyForAdminAcceptance(agencyEmail, vid, cvid);
          }
        }
    },
    {
      method: 'GET',
      path: '/admin/job/{vid}/{clientEmail}',
      config: {
          auth: {
              strategy: 'hrns-cookie',
              scope: 'admin'
          },
          handler: (request, reply) => {
            let opts = { title: 'Success!' };
            let vid = request.params.vid;
            let clientEmail = request.params.clientEmail;
            emailClientAboutNewCandidates(clientEmail, vid, (res) => {
              if (res) {
                  opts.message = 'Great! We\'ve notified the client of new candidates for this vacancy! Click here to go back to the vacancy page';
                  reply.view('message', opts, layout);
              } else {
                  opts.title = 'Uh oh...';
                  opts.message = 'Looks like something went wrong.... Try again...';
                  reply.view('message', opts, layout);
              }
            });
          }
        }
    }]);
    return next();
};

exports.register.attributes = {
    name: 'AdminJob'
};
<commit_msg>tidy up adminjob<commit_after>'use strict';

const emailClientOnAdminVacancyRemoval = require('../utils/mailgun.js').emailClientOnAdminVacancyRemoval;
const emailAgencyForAdminAcceptance    = require('../utils/app.js').emailAgencyForAdminAcceptance;
const emailClientAboutNewCandidates    = require('../utils/app.js').emailClientAboutNewCandidates;
const emailAgencyForAdminRejection     = require('../utils/mailgun.js').emailAgencyForAdminRejection;
const getSetMembersInfo                = require('../../db/redis.js').getSetMembersInfo;
const getVacancyDetails                = require('../../db/redis.js').getVacancyDetails;
const removeVacancy                    = require('../../db/redis.js').removeVacancy;
const adminApproveCV                   = require('../../db/redis.js').adminApproveCV;
const removeCV                         = require('../../db/redis.js').removeCV;

const client  = require('../../db/client.js');
const mailgun = require('../utils/mailgun.js');
const layout  = { layout: 'admin' };

exports.register = (server, options, next) => {

    server.route([{
        method: 'GET',
        path: '/admin/job/{vid}',
        config: {
            auth: {
                strategy: 'hrns-cookie',
                scope: 'admin'
            },
            handler: (request, reply) => {
                let vid  = request.params.vid;
                let opts = { title: 'Job page', vid: vid };

                getVacancyDetails(vid, (res) => {
                  if (res) {
                    let shortlist    = vid + 'adminShortlist';
                    opts.clientEmail = res.clientEmail;
                    opts.data        = res;

                    getSetMembersInfo(shortlist, (res) => {
                        if (res) {
                          opts.cvs = res;
                        } else {
                          opts.message ='There are no candidates for you to approve at the moment... come back when there are!';
                        }
                        reply.view('adminjob', opts, layout);
                    });
                  } else {
                    opts.message = 'Sorry, something went wrong, please try again';
                    return reply.view('message', opts, layout);
                  }
                });
            }
        }
    }, {
        method: 'GET',
        path: '/admin/job/remove/{vid}',
        config: {
            auth: {
                strategy: 'hrns-cookie',
                scope: 'admin'
            },
            handler: (request, reply) => {
                let opts = { title: 'Sorry...', message: 'Something went wrong, please go back and try again' };
                let vid = request.params.vid;

                getVacancyDetails(vid, (res) => {
                    if (res) {
                      let clientEmail  = res.clientEmail;
                      let clientId     = res.clientId;
                      let jobTitle     = res.jobTitle;
                      opts.clientEmail = clientEmail;

                      emailClientOnAdminVacancyRemoval.to   = clientEmail;
                      emailClientOnAdminVacancyRemoval.html = emailClientOnAdminVacancyRemoval.html.replace('-jobTitle-', jobTitle);
                      mailgun.messages().send(emailClientOnAdminVacancyRemoval);

                      removeVacancy(vid, clientId, (res) => {
                          if (res) {
                              opts.title = 'Removal successful!';
                              opts.message = 'You have successfully removed this vacancy... Return home';
                              reply.view('message', opts, layout);
                          }
                      });
                    } else {
                        reply.view('message', opts, layout);
                    }
                });
            }
        }
    }, {
      method: 'GET',
      path: '/admin/job/reject',
      config: {
          auth: {
              strategy: 'hrns-cookie',
              scope: 'admin'
          },
          handler: (request, reply) => {
            let agencyEmail = request.query.agencyEmail;
            let cvid        = request.query.cvid;
            let vid         = request.query.vid;
            let set         = vid + 'adminShortlist';

            emailAgencyForAdminRejection.to = agencyEmail;

            client.hget(cvid, 'candidateName', (err, res) => {
              if (res) {
                let candidateName = res;
                client.hgetall(vid, (err, res) => {
                  if (res) {
                    let companyName = res.companyName;
                    let jobTitle    = res.jobTitle;

                    emailAgencyForAdminRejection.html = emailAgencyForAdminRejection.html.replace('-candidateName-', candidateName).replace('-jobTitle-', jobTitle).replace('-companyName-', companyName);
                    mailgun.messages().send(emailAgencyForAdminRejection);

                    removeCV(cvid, set, (res) => {
                          if (res) {
                            reply(true);
                          } else {
                            reply(false);
                          }
                      });
                  } else {
                    reply(false);
                  }
                });
              } else {
                reply(false);
              }
            });
          }
        }
    }, {
      method: 'GET',
      path: '/rating/',
      config: {
          auth: {
              strategy: 'hrns-cookie',
              scope: 'admin'
          },
          handler: (request, reply) => {
              let vid         = request.query.vid;
              let rating      = request.query.rating;
              let agencyEmail = request.query.agencyEmail;
              let cvid        = request.query.cvid;
              let message     = 'Something went wrong... please try again';

              emailAgencyForAdminAcceptance(agencyEmail, vid, cvid);

               adminApproveCV(cvid, vid, rating, (res) => {
                  if (res) {
                    reply(cvid);
                  } else {
                     reply(message);
                  }
               });
          }
        }
    },{
      method: 'GET',
      path: '/admin/job/{vid}/{clientEmail}',
      config: {
          auth: {
              strategy: 'hrns-cookie',
              scope: 'admin'
          },
          handler: (request, reply) => {
            let opts        = { title: 'Success!' };
            let vid         = request.params.vid;
            let clientEmail = request.params.clientEmail;

            emailClientAboutNewCandidates(clientEmail, vid, (res) => {
              if (res) {
                  opts.message = 'Great! We\'ve notified the client of new candidates for this vacancy! Click here to go back to the vacancy page';
                  reply.view('message', opts, layout);
              } else {
                  opts.message = 'Looks like something went wrong.... Try again...';
                  reply.view('message', opts, layout);
              }
            });
          }
        }
    }]);
    return next();
};

exports.register.attributes = {
    name: 'AdminJob'
};
<|endoftext|>


<commit_before>(function() {
    var clientId = "clientId-" + Math.floor(Math.random() * (1000000 - 1) + 1)
    console.log("WebSocket clientId: " + clientId);

    var token = getCookie("X-Token");
    var baseUrl = undefined;
    var linkObjs = undefined;
    var websocket = undefined;
    var timeoutFn = undefined;

    function WebSocketTest()
    {
        if ("WebSocket" in window)
        {
            console.log("WebSocket is supported by your Browser!");

            var self = this;

            var open = function() {
                console.log("Connection is opened...");
                var wsScheme =
                     window.location.href.startsWith("https") ? "wss" : "ws";
                self.ws = new WebSocket(wsScheme + "://" + location.hostname
                    + (location.port ? ':' + location.port : '')
                    + location.pathname + "updates/" + clientId);

                /*
                self.ws.onopen = function()
                {
                    ws.send("Message to send");
                    console.log("Message is sent...");
                };
                */

                self.ws.onmessage = function (evt)
                {
                    var msg = JSON.parse(evt.data).value;
                    var br = document.createElement("br");
                    byId("messages").appendChild(br);
                    var textnode = document.createTextNode(msg);
                    byId("messages").appendChild(textnode);
                    window.history.back();
                    console.log(window.history);
                };

                self.ws.onclose = function()
                {
                    console.log("Connection is closed...");
                    if (token) open();
                };
            }
            open();
        }

        else
        {
            // The browser doesn't support WebSocket
            console.log("WebSocket NOT supported by your Browser!");
        }
        return self.ws;
    }

    window.ajaxGet = function(url, method) {
        return new Promise(function(resolve, reject) {
            let req = new XMLHttpRequest();
            req.open(method || "GET", url);
            req.setRequestHeader('Cache-Control', 'no-cache');
            req.onload = function() {
                if (req.status === 200) {
                    const links = req.getResponseHeader("Link");
                    if (links) {
                        linkObjs = links.split(",").map(parseLink);
                        baseUrl = linkObjs[0].url;
                    } else {
                        linkObjs = [];
                    }
                    resolve(req.response);
                } else {
                    reject(new Error(req.statusText));
                }
            };

            req.onerror = function() {
                reject(new Error("Network error"));
            };

            req.send();
        });
    }

    window.ajaxPost = function(url, data) {
        return new Promise(function(resolve, reject) {
            let req = new XMLHttpRequest();
            req.open("POST", fullUrl(url));
            req.setRequestHeader("Content-type", "application/json");
            const payload = extractPayload(token);
            if (typeof payload !== "undefined") {
                req.setRequestHeader("Authorization", "Bearer " + token);
            }
            req.onload = function() {
                if (req.status === 200) {
                    var t = req.getResponseHeader("X-Token");
                    if (typeof t !== "undefined") {
                        token = t;
                    }
                    resolve(req.response);
                } else {
                    reject(new Error(req.statusText));
                }
            };

            req.onerror = function() {
                reject(new Error("Network error"));
            };

            req.send(JSON.stringify(data));
        });
    }

    function extractPayload() {
        if (typeof token !== "undefined") {
            const parts = token.split('.');
            if (parts.length === 3) {
                const payload = JSON.parse(
                    decodeURIComponent(escape(atob(parts[1]))));
                if (typeof payload !== "undefined") {
                    const now = new Date().getTime() / 1000;
                    if (now <= payload.exp) {
                        const timeout = Math.ceil(payload.exp - now);
                        if (timeoutFn) clearTimeout(timeoutFn);
                        timeoutFn = setTimeout(
                            function() { extractPayload(); },
                            Math.min(timeout * 1000, 10000));
                        byId("login-user").innerHTML =
                            payload.name + " (" + timeout + "s)";
                        clientId = payload.sub;
                        if (!websocket) websocket = WebSocketTest();
                        return payload;
                    }
                }
            }
            token = undefined;
            if (websocket) {
                byId("login-user").innerHTML = "";
                websocket.ws.close();
                websocket = undefined;
            }
        }
        return undefined;
    }

    function addScripts(el) {
        var scripts = el.getElementsByTagName("script");
        var form = el.firstElementChild;
        for (i = 0; i < scripts.length; i++) {
            var evalFn = function() {
                return eval(scripts[i].innerHTML);
            };
            evalFn.call(form);
        }
    }

    var el = null;
    function router () {
        el = el || byId('view');
        var url = fullUrl(location.hash.slice(2)) || baseUrl;
        if (!url && !linkObjs) {
            ajaxGet(window.location.href, "HEAD").then(
                function(data) {
                    url = baseUrl;
                    router();
                }
            );
            return;
        }

        if (el && url) {
            ajaxGet(url)
                .then(function(data) {
                    el.innerHTML =
                        data.replace(/(\s+href=")\//g, "$1#/");
                    addScripts(el);
                    var pos = url.indexOf("#");
                    if (pos >= 0) {
                        var goal = url.substring(pos + 1);
                        byId(goal).scrollIntoView();
                    }
                })
                .catch(function(e) {
                    el.innerHTML = e;
                });
        }
    }

    const fullUrl = function(url) {
        const path = url[0] === '/' ? url.slice(1) : url;
        return location.origin + location.pathname + path;
    };

    const dequote = function(str) {
        return str.replace(/"/g, '');
    };

    const parseLink = function(link) {
        const linkObj = {};
        const re = /<([^>]+)>(.*)/g;
        const result = re.exec(link.trim());
        if (result && result.length >= 3) {
            linkObj.url = result[1];
            const linkArr = result[2].split(";");
            const linkObjArr = linkArr.map(function(linkItem) {
                const linkItemArr = linkItem.trim().split("=");
                if (linkItemArr.length >= 2) {
                    const value = dequote(linkItemArr[1]);
                    linkObj[linkItemArr[0]] = value;
                }
            });
        }
        return linkObj;
    };

    window.byId = function(id) {
        return document.getElementById(id);
    }

    window.isHidden = function(el) {
        var style = window.getComputedStyle(el);
        return (style.display === 'none')
    }

    function getCookie(cname) {
        var name = cname + "=";
        var decodedCookie = decodeURIComponent(document.cookie);
        var ca = decodedCookie.split(';');
        for(var i = 0; i <ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }

    const login = function() {
        window.location.assign("https://accounts.google.com/o/oauth2/v2/auth?client_id=33475451407-kv7l7blhf3jiha12c95doqvunb0uajop.apps.googleusercontent.com&redirect_uri=https://feca.mooo.com/app/auth/callback&response_type=code&access_type=online&scope=email openid profile&nonce=feca&state=feca|" + encodeURIComponent(window.location.href));
    };

    if (token) extractPayload();

    window.addEventListener('hashchange', router);
    window.addEventListener('load', router);
    byId('btnLogin').addEventListener('click', login);
    <!--var webSocket = WebSocketTest();-->
})();
<commit_msg>Store token in sessionStorage<commit_after>(function() {
    var clientId = "clientId-" + Math.floor(Math.random() * (1000000 - 1) + 1)

    var token = window.sessionStorage.getItem("X-Token");
    var baseUrl = undefined;
    var linkObjs = undefined;
    var websocket = undefined;
    var timeoutFn = undefined;

    function WebSocketTest() {
        if ("WebSocket" in window) {
            console.log("WebSocket is supported by your Browser!");

            var self = this;

            var open = function() {
                console.log("Connection is opened...");
                var wsScheme =
                     window.location.href.startsWith("https") ? "wss" : "ws";
                self.ws = new WebSocket(wsScheme + "://" + location.hostname
                    + (location.port ? ':' + location.port : '')
                    + location.pathname + "updates/" + clientId);

                /*
                self.ws.onopen = function()
                {
                    ws.send("Message to send");
                    console.log("Message is sent...");
                };
                */

                self.ws.onmessage = function (evt) {
                    var msg = JSON.parse(evt.data).value;
                    var br = document.createElement("br");
                    byId("messages").appendChild(br);
                    var textnode = document.createTextNode(msg);
                    byId("messages").appendChild(textnode);
                    window.history.back();
                    console.log(window.history);
                };

                self.ws.onclose = function() {
                    console.log("Connection is closed...");
                    if (token) open();
                };
            }
            open();
        } else {
            // The browser doesn't support WebSocket
            console.log("WebSocket NOT supported by your Browser!");
        }
        return self.ws;
    }

    window.ajaxGet = function(url, method) {
        return new Promise(function(resolve, reject) {
            let req = new XMLHttpRequest();
            req.open(method || "GET", url);
            req.setRequestHeader('Cache-Control', 'no-cache');
            req.onload = function() {
                if (req.status === 200) {
                    const links = req.getResponseHeader("Link");
                    if (links) {
                        linkObjs = links.split(",").map(parseLink);
                        baseUrl = linkObjs[0].url;
                    } else {
                        linkObjs = [];
                    }
                    resolve(req.response);
                } else {
                    reject(new Error(req.statusText));
                }
            };

            req.onerror = function() {
                reject(new Error("Network error"));
            };

            req.send();
        });
    }

    window.ajaxPost = function(url, data) {
        return new Promise(function(resolve, reject) {
            let req = new XMLHttpRequest();
            req.open("POST", fullUrl(url));
            req.setRequestHeader("Content-type", "application/json");
            const payload = extractPayload(token);
            if (typeof payload !== "undefined") {
                req.setRequestHeader("Authorization", "Bearer " + token);
            }
            req.onload = function() {
                if (req.status === 200) {
                    var t = req.getResponseHeader("X-Token");
                    if (typeof t !== "undefined") {
                        token = t;
                        window.sessionStorage.setItem("X-Token", token);
                    }
                    resolve(req.response);
                } else {
                    reject(new Error(req.statusText));
                }
            };

            req.onerror = function() {
                reject(new Error("Network error"));
            };

            req.send(JSON.stringify(data));
        });
    }

    function extractPayload() {
        if (token) {
            const parts = token.split('.');
            if (parts.length === 3) {
                const payload = JSON.parse(
                    decodeURIComponent(escape(atob(parts[1]))));
                if (typeof payload !== "undefined") {
                    const now = new Date().getTime() / 1000;
                    if (now <= payload.exp) {
                        const timeout = Math.ceil(payload.exp - now);
                        if (timeoutFn) clearTimeout(timeoutFn);
                        timeoutFn = setTimeout(
                            function() { extractPayload(); },
                            Math.min(timeout * 1000, 10000));
                        byId("login-user").innerHTML =
                            payload.name + " (" + timeout + "s)";
                        clientId = payload.sub;
                        if (!websocket) websocket = WebSocketTest();
                        return payload;
                    }
                }
            }
            token = undefined;
            window.sessionStorage.removeItem("X-Token");
            if (websocket) {
                byId("login-user").innerHTML = "";
                websocket.ws.close();
                websocket = undefined;
            }
        }
        return undefined;
    }

    function addScripts(el) {
        var scripts = el.getElementsByTagName("script");
        var form = el.firstElementChild;
        for (i = 0; i < scripts.length; i++) {
            var evalFn = function() {
                return eval(scripts[i].innerHTML);
            };
            evalFn.call(form);
        }
    }

    var el = null;
    function router () {
        el = el || byId('view');
        var url = fullUrl(location.hash.slice(2)) || baseUrl;
        if (!url && !linkObjs) {
            ajaxGet(window.location.href, "HEAD").then(
                function(data) {
                    url = baseUrl;
                    router();
                }
            );
            return;
        }

        if (el && url) {
            ajaxGet(url)
                .then(function(data) {
                    el.innerHTML =
                        data.replace(/(\s+href=")\//g, "$1#/");
                    addScripts(el);
                    var pos = url.indexOf("#");
                    if (pos >= 0) {
                        var goal = url.substring(pos + 1);
                        byId(goal).scrollIntoView();
                    }
                })
                .catch(function(e) {
                    el.innerHTML = e;
                });
        }
    }

    const fullUrl = function(url) {
        const path = url[0] === '/' ? url.slice(1) : url;
        return location.origin + location.pathname + path;
    };

    const dequote = function(str) {
        return str.replace(/"/g, '');
    };

    const parseLink = function(link) {
        const linkObj = {};
        const re = /<([^>]+)>(.*)/g;
        const result = re.exec(link.trim());
        if (result && result.length >= 3) {
            linkObj.url = result[1];
            const linkArr = result[2].split(";");
            const linkObjArr = linkArr.map(function(linkItem) {
                const linkItemArr = linkItem.trim().split("=");
                if (linkItemArr.length >= 2) {
                    const value = dequote(linkItemArr[1]);
                    linkObj[linkItemArr[0]] = value;
                }
            });
        }
        return linkObj;
    };

    window.byId = function(id) {
        return document.getElementById(id);
    }

    window.isHidden = function(el) {
        var style = window.getComputedStyle(el);
        return (style.display === 'none')
    }

    function getCookie(cname) {
        var name = cname + "=";
        var decodedCookie = decodeURIComponent(document.cookie);
        var ca = decodedCookie.split(';');
        for(var i = 0; i <ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0) {
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }

    const login = function() {
        window.location.assign("https://accounts.google.com/o/oauth2/v2/auth?client_id=33475451407-kv7l7blhf3jiha12c95doqvunb0uajop.apps.googleusercontent.com&redirect_uri=https://feca.mooo.com/app/auth/callback&response_type=code&access_type=online&scope=email openid profile&nonce=feca&state=feca|" + encodeURIComponent(window.location.href));
    };

    if (token) extractPayload();

    window.addEventListener('hashchange', router);
    window.addEventListener('load', router);
    byId('btnLogin').addEventListener('click', login);
    <!--var webSocket = WebSocketTest();-->
})();
<|endoftext|>


<commit_before>'use strict';

goog.provide('Blockly.Python.actuator');
goog.require('Blockly.Python');

Blockly.Python.microbit_music_play_built_in = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var dropdown_melody = block.getFieldValue('melody');
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var checkbox_wait = block.getFieldValue('wait') == 'TRUE' ? 'True' : 'False';
    var checkbox_loop = block.getFieldValue('loop') == 'TRUE' ? 'True' : 'False';
    var code = 'music.play(music.' + dropdown_melody + ', pin=pin' + pin +', wait=' + checkbox_wait + ', loop=' + checkbox_loop + ')\n';
    return code;
};

Blockly.Python.microbit_music_play_built_in_easy = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var dropdown_melody = block.getFieldValue('melody');
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var code = 'music.play(music.' + dropdown_melody + ', pin=pin' + pin +')\n';
    return code;
};

Blockly.Python.microbit_music_pitch_delay = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    Blockly.Python.definitions_['import_math'] = 'import math';
    var number_pitch = Blockly.Python.valueToCode(block, 'pitch', Blockly.Python.ORDER_ATOMIC);
    var number_duration = Blockly.Python.valueToCode(block, 'duration', Blockly.Python.ORDER_ATOMIC);
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var checkbox_wait = block.getFieldValue('wait') == 'TRUE' ? 'True' : 'False';
    var code = 'music.pitch(round(' + number_pitch + '), round(' + number_duration + '), pin' + pin + ', wait = ' + checkbox_wait + ')\n';
    return code;
};

Blockly.Python.microbit_music_pitch = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    Blockly.Python.definitions_['import_math'] = 'import math';
    var number_pitch = Blockly.Python.valueToCode(block, 'pitch', Blockly.Python.ORDER_ATOMIC);
    // var number_duration = Blockly.Python.valueToCode(block, 'duration', Blockly.Python.ORDER_ATOMIC);
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var code = 'music.pitch(round(' + number_pitch + '), pin=pin' + pin + ')\n';
    return code;
};

Blockly.Python.microbit_music_play_list_of_notes = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var value_notes = Blockly.Python.valueToCode(block, 'notes', Blockly.Python.ORDER_ATOMIC) ||'[]';
    var checkbox_wait = block.getFieldValue('wait') == 'TRUE' ? 'True' : 'False';
    var checkbox_loop = block.getFieldValue('loop') == 'TRUE' ? 'True' : 'False';
    var code = 'music.play(' + value_notes + ', pin=pin' + pin + ', wait=' + checkbox_wait + ', loop=' + checkbox_loop + ')\n';
    return code;
};

Blockly.Python.microbit_music_reset = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var code = 'music.reset()\n';
    return code;
};

Blockly.Python.microbit_music_stop = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var code = 'music.stop(pin' + pin + ')\n';
    return code;
};

Blockly.Python.microbit_music_get_tempo = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var code = 'music.get_tempo()';
    return [code, Blockly.Python.ORDER_MEMBER];
};

Blockly.Python.tone_set_tempo=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    var bpm = Blockly.Python.valueToCode(this, 'BPM', Blockly.Python.ORDER_ASSIGNMENT);
    var ticks = Blockly.Python.valueToCode(this, 'TICKS', Blockly.Python.ORDER_ASSIGNMENT);
    var code = "music.set_tempo(ticks="+ ticks +", bpm="+ bpm +")\n";
    return code;
};

Blockly.Python.speech_translate=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.translate("+ text +")\n";
    return code
};

Blockly.Python.speech_say=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var mode = this.getFieldValue("MODE");
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var pitch = Blockly.Python.valueToCode(this, 'pitch', Blockly.Python.ORDER_ATOMIC);
    var speed = Blockly.Python.valueToCode(this, 'speed', Blockly.Python.ORDER_ATOMIC);
    var mouth = Blockly.Python.valueToCode(this, 'mouth', Blockly.Python.ORDER_ATOMIC);
    var throat = Blockly.Python.valueToCode(this, 'throat', Blockly.Python.ORDER_ATOMIC);
    var code = "speech."+mode+"("+ text +", pitch="+pitch+", speed="+speed+", mouth="+mouth+", throat="+throat+")\n";
    return code
};

// Blockly.Python.speech_sing=function(){
//   Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
//   Blockly.Python.definitions_['import_speech'] = 'import speech';
//   var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
//   var pitch = Blockly.Python.valueToCode(this, 'pitch', Blockly.Python.ORDER_ATOMIC);
//   var speed = Blockly.Python.valueToCode(this, 'speed', Blockly.Python.ORDER_ATOMIC);
//   var mouth = Blockly.Python.valueToCode(this, 'mouth', Blockly.Python.ORDER_ATOMIC);
//   var throat = Blockly.Python.valueToCode(this, 'throat', Blockly.Python.ORDER_ATOMIC);
//   var code = "speech.sing("+ text +", pitch="+pitch+", speed="+speed+", mouth="+mouth+", throat="+throat+")\n";
//   return code
// };

// Blockly.Python.speech_prenounce=function(){
//   Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
//   Blockly.Python.definitions_['import_speech'] = 'import speech';
//   var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
//   var pitch = Blockly.Python.valueToCode(this, 'pitch', Blockly.Python.ORDER_ATOMIC);
//   var speed = Blockly.Python.valueToCode(this, 'speed', Blockly.Python.ORDER_ATOMIC);
//   var mouth = Blockly.Python.valueToCode(this, 'mouth', Blockly.Python.ORDER_ATOMIC);
//   var throat = Blockly.Python.valueToCode(this, 'throat', Blockly.Python.ORDER_ATOMIC);
//   var code = "speech.pronounce("+ text +", pitch="+pitch+", speed="+speed+", mouth="+mouth+", throat="+throat+")\n";
//   return code
// };

Blockly.Python.speech_say_easy=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.say("+ text +")\n";
    return code
};

Blockly.Python.speech_sing_easy=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.sing("+ text +")\n";
    return code
};

Blockly.Python.speech_prenounce_easy=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.pronounce("+ text +")\n";
    return code
};

Blockly.Python.servo_move = function() {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.setups_['class_servo'] =
        'class Servo:\n'+
        '    def __init__(self, pin, freq=50, min_us=600, max_us=2400, angle=180):\n'+
        '        self.min_us = min_us\n'+
        '        self.max_us = max_us\n'+
        '        self.us = 0\n'+
        '        self.freq = freq\n'+
        '        self.angle = angle\n'+
        '        self.analog_period = 0\n'+
        '        self.pin = pin\n'+
        '        analog_period = round((1/self.freq) * 1000)\n'+
        '        self.pin.set_analog_period(analog_period)\n\n'+

        '    def write_us(self, us):\n'+
        '        us = min(self.max_us, max(self.min_us, us))\n'+
        '        duty = round(us * 1024 * self.freq // 1000000)\n'+
        '        self.pin.write_analog(duty)\n'+
        '        self.pin.write_digital(0)\n\n'+
        '    def write_angle(self, degrees=None):\n'+
        '        degrees = degrees % 360\n'+
        '        total_range = self.max_us - self.min_us\n'+
        '        us = self.min_us + total_range * degrees // self.angle\n'+
        '        self.write_us(us)\n'+
        '\n';

    Blockly.Python.setups_['mixly_servo_write_angle']=
        'def mixly_write_angle(pin,ang,delay):\n'+
        '    Servo(pin).write_angle(ang)\n'+
        '    sleep(delay)\n';
    var dropdown_pin = Blockly.Python.valueToCode(this, 'PIN',Blockly.Python.ORDER_ATOMIC);
    var value_degree = Blockly.Python.valueToCode(this, 'DEGREE', Blockly.Python.ORDER_ATOMIC);
    //value_degree = value_degree.replace('(','').replace(')','')
    var delay_time = Blockly.Python.valueToCode(this, 'DELAY_TIME', Blockly.Python.ORDER_ATOMIC) || '0'
    //delay_time = delay_time.replace('(','').replace(')','');

    /* var code = 'Servo(pin'+dropdown_pin+').write_angle('+value_degree+')\n'+'sleep(' + delay_time + ')\n';
     return code;*/
    var code= 'mixly_servo_write_angle('+dropdown_pin+','+value_degree+','+delay_time+')\n';
    return code;
};
<commit_msg>fix actuator.js<commit_after>'use strict';

goog.provide('Blockly.Python.actuator');
goog.require('Blockly.Python');

Blockly.Python.microbit_music_play_built_in = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var dropdown_melody = block.getFieldValue('melody');
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var checkbox_wait = block.getFieldValue('wait') == 'TRUE' ? 'True' : 'False';
    var checkbox_loop = block.getFieldValue('loop') == 'TRUE' ? 'True' : 'False';
    var code = 'music.play(music.' + dropdown_melody + ', pin=pin' + pin +', wait=' + checkbox_wait + ', loop=' + checkbox_loop + ')\n';
    return code;
};

Blockly.Python.microbit_music_play_built_in_easy = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var dropdown_melody = block.getFieldValue('melody');
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var code = 'music.play(music.' + dropdown_melody + ', pin=pin' + pin +')\n';
    return code;
};

Blockly.Python.microbit_music_pitch_delay = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    Blockly.Python.definitions_['import_math'] = 'import math';
    var number_pitch = Blockly.Python.valueToCode(block, 'pitch', Blockly.Python.ORDER_ATOMIC);
    var number_duration = Blockly.Python.valueToCode(block, 'duration', Blockly.Python.ORDER_ATOMIC);
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var checkbox_wait = block.getFieldValue('wait') == 'TRUE' ? 'True' : 'False';
    var code = 'music.pitch(round(' + number_pitch + '), round(' + number_duration + '), pin' + pin + ', wait = ' + checkbox_wait + ')\n';
    return code;
};

Blockly.Python.microbit_music_pitch = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    Blockly.Python.definitions_['import_math'] = 'import math';
    var number_pitch = Blockly.Python.valueToCode(block, 'pitch', Blockly.Python.ORDER_ATOMIC);
    // var number_duration = Blockly.Python.valueToCode(block, 'duration', Blockly.Python.ORDER_ATOMIC);
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var code = 'music.pitch(round(' + number_pitch + '), pin=pin' + pin + ')\n';
    return code;
};

Blockly.Python.microbit_music_play_list_of_notes = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var value_notes = Blockly.Python.valueToCode(block, 'notes', Blockly.Python.ORDER_ATOMIC) ||'[]';
    var checkbox_wait = block.getFieldValue('wait') == 'TRUE' ? 'True' : 'False';
    var checkbox_loop = block.getFieldValue('loop') == 'TRUE' ? 'True' : 'False';
    var code = 'music.play(' + value_notes + ', pin=pin' + pin + ', wait=' + checkbox_wait + ', loop=' + checkbox_loop + ')\n';
    return code;
};

Blockly.Python.microbit_music_reset = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var code = 'music.reset()\n';
    return code;
};

Blockly.Python.microbit_music_stop = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var pin = Blockly.Python.valueToCode(block, 'PIN', Blockly.Python.ORDER_ATOMIC);
    var code = 'music.stop(pin' + pin + ')\n';
    return code;
};

Blockly.Python.microbit_music_get_tempo = function(block) {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_music'] = 'import music';
    var code = 'music.get_tempo()';
    return [code, Blockly.Python.ORDER_MEMBER];
};

Blockly.Python.tone_set_tempo=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    var bpm = Blockly.Python.valueToCode(this, 'BPM', Blockly.Python.ORDER_ASSIGNMENT);
    var ticks = Blockly.Python.valueToCode(this, 'TICKS', Blockly.Python.ORDER_ASSIGNMENT);
    var code = "music.set_tempo(ticks="+ ticks +", bpm="+ bpm +")\n";
    return code;
};

Blockly.Python.speech_translate=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.translate("+ text +")\n";
    return code
};

Blockly.Python.speech_say=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var mode = this.getFieldValue("MODE");
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var pitch = Blockly.Python.valueToCode(this, 'pitch', Blockly.Python.ORDER_ATOMIC);
    var speed = Blockly.Python.valueToCode(this, 'speed', Blockly.Python.ORDER_ATOMIC);
    var mouth = Blockly.Python.valueToCode(this, 'mouth', Blockly.Python.ORDER_ATOMIC);
    var throat = Blockly.Python.valueToCode(this, 'throat', Blockly.Python.ORDER_ATOMIC);
    var code = "speech."+mode+"("+ text +", pitch="+pitch+", speed="+speed+", mouth="+mouth+", throat="+throat+")\n";
    return code
};

// Blockly.Python.speech_sing=function(){
//   Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
//   Blockly.Python.definitions_['import_speech'] = 'import speech';
//   var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
//   var pitch = Blockly.Python.valueToCode(this, 'pitch', Blockly.Python.ORDER_ATOMIC);
//   var speed = Blockly.Python.valueToCode(this, 'speed', Blockly.Python.ORDER_ATOMIC);
//   var mouth = Blockly.Python.valueToCode(this, 'mouth', Blockly.Python.ORDER_ATOMIC);
//   var throat = Blockly.Python.valueToCode(this, 'throat', Blockly.Python.ORDER_ATOMIC);
//   var code = "speech.sing("+ text +", pitch="+pitch+", speed="+speed+", mouth="+mouth+", throat="+throat+")\n";
//   return code
// };

// Blockly.Python.speech_prenounce=function(){
//   Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
//   Blockly.Python.definitions_['import_speech'] = 'import speech';
//   var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
//   var pitch = Blockly.Python.valueToCode(this, 'pitch', Blockly.Python.ORDER_ATOMIC);
//   var speed = Blockly.Python.valueToCode(this, 'speed', Blockly.Python.ORDER_ATOMIC);
//   var mouth = Blockly.Python.valueToCode(this, 'mouth', Blockly.Python.ORDER_ATOMIC);
//   var throat = Blockly.Python.valueToCode(this, 'throat', Blockly.Python.ORDER_ATOMIC);
//   var code = "speech.pronounce("+ text +", pitch="+pitch+", speed="+speed+", mouth="+mouth+", throat="+throat+")\n";
//   return code
// };

Blockly.Python.speech_say_easy=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.say("+ text +")\n";
    return code
};

Blockly.Python.speech_sing_easy=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.sing("+ text +")\n";
    return code
};

Blockly.Python.speech_prenounce_easy=function(){
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.definitions_['import_speech'] = 'import speech';
    var text = Blockly.Python.valueToCode(this, 'VAR', Blockly.Python.ORDER_ATOMIC);
    var code = "speech.pronounce("+ text +")\n";
    return code
};

Blockly.Python.servo_move = function() {
    Blockly.Python.definitions_['import_microbit_*'] = 'from microbit import *';
    Blockly.Python.setups_['class_servo'] =
        'class Servo:\n'+
        '    def __init__(self, pin, freq=50, min_us=600, max_us=2400, angle=180):\n'+
        '        self.min_us = min_us\n'+
        '        self.max_us = max_us\n'+
        '        self.us = 0\n'+
        '        self.freq = freq\n'+
        '        self.angle = angle\n'+
        '        self.analog_period = 0\n'+
        '        self.pin = pin\n'+
        '        analog_period = round((1/self.freq) * 1000)\n'+
        '        self.pin.set_analog_period(analog_period)\n\n'+

        '    def write_us(self, us):\n'+
        '        us = min(self.max_us, max(self.min_us, us))\n'+
        '        duty = round(us * 1024 * self.freq // 1000000)\n'+
        '        self.pin.write_analog(duty)\n'+
        '        self.pin.write_digital(0)\n\n'+
        '    def write_angle(self, degrees=None):\n'+
        '        degrees = degrees % 360\n'+
        '        total_range = self.max_us - self.min_us\n'+
        '        us = self.min_us + total_range * degrees // self.angle\n'+
        '        self.write_us(us)\n'+
        '\n';

    Blockly.Python.setups_['mixly_servo_write_angle']=
        'def mixly_servo_write_angle(pin,ang,delay):\n'+
        '    Servo(pin).write_angle(ang)\n'+
        '    sleep(delay)\n';
    var dropdown_pin = Blockly.Python.valueToCode(this, 'PIN',Blockly.Python.ORDER_ATOMIC);
    var value_degree = Blockly.Python.valueToCode(this, 'DEGREE', Blockly.Python.ORDER_ATOMIC);
    //value_degree = value_degree.replace('(','').replace(')','')
    var delay_time = Blockly.Python.valueToCode(this, 'DELAY_TIME', Blockly.Python.ORDER_ATOMIC) || '0'
    //delay_time = delay_time.replace('(','').replace(')','');

    /* var code = 'Servo(pin'+dropdown_pin+').write_angle('+value_degree+')\n'+'sleep(' + delay_time + ')\n';
     return code;*/
    var code= 'mixly_servo_write_angle('+dropdown_pin+','+value_degree+','+delay_time+')\n';
    return code;
};
<|endoftext|>


<commit_before>function bind(f, scope) {
    function wrapper() {
        return f.apply(scope, arguments);
    }
    return wrapper;
};

hcomments = {
    comments: function(o) {
        this.form = o.form;
        this.wrapper = o.wrapper;
        this.comments = o.comments;
        this.remove = o.remove || '';

        this.form.append('<input type="hidden" name="async" value="1" />');
        o.form.ajaxForm({
            error: function(request, textStatus, errorThrown) {
                if(request.status == 403)
                    alert('Your comment has been moderated');
                else
                    alert('Cannot post your comment');
            },
            success: bind(function(data, textStatus) {
                var data = this.filterOut($(data));
                if(data) {
                    data
                        .hide()
                        .appendTo(this.wrapper)
                        .fadeIn("slow");
                    this.addRemoveLink(data);
                    this.addReplyLink(data);
                }
            }, this)
        });
        this.addRemoveLink();
        this.addReplyLink();
    },
    filterOut: function(c) {
        /*
         * django comment è abbastanza furbo da non inserire due volte lo
         * stesso commento (double posting), quindi c potrebbe avere un id già
         * presente
         */
        return $('#' + c.attr('id')).length == 0 ? c : null
    },
    addRemoveLink: function(target) {
        if(!this.remove)
            return;
        if(!target)
            target = $('li.user-comment');
        $('Remove |')
            .click(bind(this._onRemoveComment, this))
            .insertBefore($('strong', target));
    },
    _onRemoveComment: function(e) {
        e.preventDefault();
        var p = $(e.target).parent('li');
        var id = p.attr('id').split('-')[1];
        $.post(this.remove, { cid: id })
        p.hide("slow", function() { $(this).remove(); });
    },
    addReplyLink: function(target) {
        if(!target)
            target = this.comments;
        $('Reply |')
            .click(bind(this._onReplyComment, this))
            .insertBefore($('strong', target));
    },
    _onReplyComment: function(e) {
        e.preventDefault();
        var p = $(e.target).parents('li');
        if($('form', p).length)
            return;
        var id = p.attr('id').split('-')[1];
        var form = this.form.clone();
        $('input[name="parent"]', form).val(id);
        form
            .ajaxForm({
                error: function(request, textStatus, errorThrown) {
                    alert('cannot post your comment');
                },
                success: bind(function(data, textStatus) {
                    var data = this.filterOut($(data));
                    if(data) {
                        data
                            .hide()
                            .insertAfter(p)
                            .fadeIn("slow");
                        this.addRemoveLink(data);
                        this.addReplyLink(data);
                    }
                }, this),
                complete: function() {
                    form.remove();
                }
            })
            .appendTo(p);
    }
};
<commit_msg>nascondo le altre form di reply quando rispondo ad un commento<commit_after>function bind(f, scope) {
    function wrapper() {
        return f.apply(scope, arguments);
    }
    return wrapper;
};

hcomments = {
    comments: function(o) {
        this.form = o.form;
        this.wrapper = o.wrapper;
        this.comments = o.comments;
        this.remove = o.remove || '';

        this.form.append('<input type="hidden" name="async" value="1" />');
        o.form.ajaxForm({
            error: function(request, textStatus, errorThrown) {
                if(request.status == 403)
                    alert('Your comment has been moderated');
                else
                    alert('Cannot post your comment');
            },
            success: bind(function(data, textStatus) {
                var data = this.filterOut($(data));
                if(data) {
                    data
                        .hide()
                        .appendTo(this.wrapper)
                        .fadeIn("slow");
                    this.addRemoveLink(data);
                    this.addReplyLink(data);
                }
            }, this)
        });
        this.addRemoveLink();
        this.addReplyLink();
    },
    filterOut: function(c) {
        /*
         * django comment è abbastanza furbo da non inserire due volte lo
         * stesso commento (double posting), quindi c potrebbe avere un id già
         * presente
         */
        return $('#' + c.attr('id')).length == 0 ? c : null
    },
    addRemoveLink: function(target) {
        if(!this.remove)
            return;
        if(!target)
            target = $('li.user-comment');
        $('Remove |')
            .click(bind(this._onRemoveComment, this))
            .insertBefore($('strong', target));
    },
    _onRemoveComment: function(e) {
        e.preventDefault();
        var p = $(e.target).parent('li');
        var id = p.attr('id').split('-')[1];
        $.post(this.remove, { cid: id })
        p.hide("slow", function() { $(this).remove(); });
    },
    addReplyLink: function(target) {
        if(!target)
            target = this.comments;
        $('Reply |')
            .click(bind(this._onReplyComment, this))
            .insertBefore($('strong', target));
    },
    _onReplyComment: function(e) {
        e.preventDefault();
        var p = $(e.target).parents('li');
        if($('form', p).length)
            return;
        $('li.replying form').remove();
        $('li.replying').removeClass('replying');
        p.addClass('replying');
        var id = p.attr('id').split('-')[1];
        var form = this.form.clone();
        $('input[name="parent"]', form).val(id);
        $('<button>Cancel</button>')
            .appendTo($('div.buttons', form))
            .click(function(e) {
                e.preventDefault();
                form.remove();
                p.removeClass('replying');
            });
        form
            .ajaxForm({
                error: function(request, textStatus, errorThrown) {
                    alert('cannot post your comment');
                },
                success: bind(function(data, textStatus) {
                    var data = this.filterOut($(data));
                    if(data) {
                        data
                            .hide()
                            .insertAfter(p)
                            .fadeIn("slow");
                        this.addRemoveLink(data);
                        this.addReplyLink(data);
                    }
                }, this),
                complete: function() {
                    form.remove();
                }
            })
            .appendTo(p);
    }
};
<|endoftext|>


<commit_before>lock = false;

// Add new (not yet released) code from Dallinger.
Dallinger.submitQuestionnaire = function (name) {
  var formSerialized = $("form").serializeArray(),
      formDict = {},
      deferred = $.Deferred();

  formSerialized.forEach(function (field) {
      formDict[field.name] = field.value;
  });

  reqwest({
    method: "post",
    url: "/question/" + participant_id,
    data: {
      question: name || "questionnaire",
      number: 1,
      response: JSON.stringify(formDict),
    },
    type: "json",
    success: function (resp) {
      deferred.resolve();
    },
    error: function (err) {
      deferred.reject();
      var errorResponse = JSON.parse(err.response);
      $("body").html(errorResponse.html);
    }
  });

  return deferred;
};

// Cribbed from Dallinger Griduniverse repo:
// https://github.com/Dallinger/Griduniverse/blob/master/dlgr/griduniverse/static/scripts/questionnaire.js
$(document).ready( function() {

  // Submit the questionnaire ONLY if we haven't clicked yet.
  if (lock===false){
      $("#submit-questionnaire").click(function() {

        // Prevent multiple submission clicks.
        lock = true;
        $(document).off('click');

        // Allow the form to submit.
        var $elements = [$("form :input"), $(this)],
            questionSubmission = Dallinger.submitQuestionnaire("questionnaire");
            console.log("Submitting questionnaire.");

        // Submit questionnaire.
        questionSubmission.done(function()
            {
              dallinger.goToPage('debriefing');
            });
    });
  }
});
<commit_msg>Use Dallinger's new participant ID variable<commit_after>lock = false;

// Add new (not yet released) code from Dallinger.
Dallinger.submitQuestionnaire = function (name) {
  var formSerialized = $("form").serializeArray(),
      formDict = {},
      deferred = $.Deferred();

  formSerialized.forEach(function (field) {
      formDict[field.name] = field.value;
  });

  reqwest({
    method: "post",
    url: "/question/" + dallinger.identity.participantId,
    data: {
      question: name || "questionnaire",
      number: 1,
      response: JSON.stringify(formDict),
    },
    type: "json",
    success: function (resp) {
      deferred.resolve();
    },
    error: function (err) {
      deferred.reject();
      var errorResponse = JSON.parse(err.response);
      $("body").html(errorResponse.html);
    }
  });

  return deferred;
};

// Cribbed from Dallinger Griduniverse repo:
// https://github.com/Dallinger/Griduniverse/blob/master/dlgr/griduniverse/static/scripts/questionnaire.js
$(document).ready( function() {

  // Submit the questionnaire ONLY if we haven't clicked yet.
  if (lock===false){
      $("#submit-questionnaire").click(function() {

        // Prevent multiple submission clicks.
        lock = true;
        $(document).off('click');

        // Allow the form to submit.
        var $elements = [$("form :input"), $(this)],
            questionSubmission = Dallinger.submitQuestionnaire("questionnaire");
            console.log("Submitting questionnaire.");

        // Submit questionnaire.
        questionSubmission.done(function()
            {
              dallinger.goToPage('debriefing');
            });
    });
  }
});
<|endoftext|>