<commit_before>import {
  createContext,
  useEffect,
  useCallback,
  useMemo,
  useRef,
  useContext,
} from 'react';
import {atomFamily, useRecoilValue, useSetRecoilState} from 'recoil';

import {sleep} from '../utility';

const WS_PROTOCOL = 'xorkevin.dev-governor_ws_v1alpha1';

const noop = Object.freeze(() => {});

const parseJSON = (s) => {
  try {
    return JSON.parse(s);
  } catch (_err) {
    return {};
  }
};

const WSDefaultOpts = Object.freeze({
  name: '__DEFAULT__',
  send: noop,
  sub: noop,
});

const WSCtx = createContext(WSDefaultOpts);

const defaultWSState = Object.freeze({
  open: false,
});

const WSState = atomFamily({
  key: 'govui:ws_state',
  default: defaultWSState,
});

const WSProvider = ({value, children}) => {
  return <WSCtx.Provider value={value}>{children}</WSCtx.Provider>;
};

const useWSValue = (name) => {
  return useRecoilValue(WSState(name));
};

const useWSValueCtx = () => {
  const {name} = useContext(WSCtx);
  return useWSValue(name);
};

const registerHandlers = (socket, sub) => {
  if (!sub) {
    return;
  }
  const {onopen, onmessage, onerror, onclose, signal} = sub;
  if (onopen) {
    socket.addEventListener('open', onopen, {signal});
  }
  if (onmessage) {
    socket.addEventListener('message', onmessage, {signal});
  }
  if (onerror) {
    socket.addEventListener('error', onerror, {signal});
  }
  if (onclose) {
    socket.addEventListener('close', onclose, {signal});
  }
};

const useWS = (
  name,
  url,
  {delayMin, delayMax, delayExp, prehook, errhook} = {},
) => {
  const setWSState = useSetRecoilState(WSState(name));

  const ws = useRef({
    socket: null,
    open: false,
    loaded: false,
    subs: new Set(),
  });

  if (!url) {
    ws.current.open = false;
  }

  if (typeof delayMin !== 'number') {
    delayMin = 250;
  }
  if (typeof delayMax !== 'number') {
    delayMax = 15000;
  }
  if (typeof delayExp !== 'number') {
    delayExp = 2;
  }

  useEffect(() => {
    ws.current.open = false;
    ws.current.loaded = false;
    setWSState({open: false});
    if (!url) {
      return;
    }
    const controller = new AbortController();
    const signal = controller.signal;
    (async () => {
      let delay = delayMin;
      // eslint-disable-next-line no-constant-condition
      while (true) {
        ws.current.open = false;
        ws.current.loaded = false;
        setWSState({open: false});

        if (prehook) {
          const err = await prehook({signal});
          if (signal.aborted) {
            return;
          }
          if (err) {
            if (errhook) {
              errhook('prehook', err);
            }
            await sleep(delay);
            if (signal.aborted) {
              return;
            }
            delay = Math.min(delay * delayExp, delayMax);
            continue;
          }
        }

        const socket = new WebSocket(url, WS_PROTOCOL);
        const socketClosed = new Promise((resolve) => {
          socket.addEventListener('close', () => {
            if (signal.aborted) {
              resolve();
              return;
            }
            ws.current.open = false;
            ws.current.loaded = false;
            setWSState({open: false});
            resolve();
          });
        });
        socket.addEventListener('open', () => {
          if (signal.aborted) {
            return;
          }
          delay = delayMin;
          ws.current.open = true;
          setWSState({open: true});
        });
        const innerController = new AbortController();
        signal.addEventListener(
          'abort',
          () => {
            socket.close(1000, 'OK');
          },
          {signal: innerController.signal},
        );
        for (const sub of ws.current.subs.values()) {
          registerHandlers(socket, sub);
        }
        ws.current.socket = socket;
        ws.current.loaded = true;
        await socketClosed;
        if (signal.aborted) {
          return;
        }
        innerController.abort();
        await sleep(delay);
        if (signal.aborted) {
          return;
        }
        delay = Math.min(delay * delayExp, delayMax);
      }
    })();
    return () => {
      controller.abort();
    };
  }, [setWSState, ws, url, delayMin, delayMax, delayExp, prehook, errhook]);

  const send = useCallback(
    (data) => {
      if (!ws.current.open) {
        errhook('send', {message: 'Not connected'});
        return;
      }
      ws.current.socket.send(data);
    },
    [ws, errhook],
  );

  const sendChan = useCallback(
    (channel, value) => {
      if (!ws.current.open) {
        errhook('send', {message: 'Not connected'});
        return;
      }
      ws.current.socket.send(
        JSON.stringify({
          channel,
          value,
        }),
      );
    },
    [ws, errhook],
  );

  const sub = useCallback(
    (f, signal) => {
      if (!f || signal.aborted) {
        return;
      }
      const sub = Object.assign({}, f, {signal});
      ws.current.subs.add(sub);
      signal.addEventListener('abort', () => {
        ws.current.subs.delete(sub);
      });
      if (ws.current.loaded) {
        registerHandlers(ws.current.socket, sub);
      }
    },
    [ws],
  );

  const subChan = useCallback(
    (chan, f, signal) => {
      if (!f || signal.aborted) {
        return;
      }
      let onmessage = f.onmessage;
      if (f.onmessage) {
        const isChanPrefix = typeof chan === 'string';
        onmessage = (e) => {
          const data = parseJSON(e.data);
          if (data === undefined || data === null) {
            return;
          }
          const {channel, value} = data;
          if (typeof channel !== 'string') {
            return;
          }
          if (isChanPrefix) {
            if (!channel.startsWith(chan)) {
              return;
            }
          } else {
            if (!chan.test(channel)) {
              return;
            }
          }
          f.onmessage(channel, value, e);
        };
      }
      const sub = Object.assign({}, f, {onmessage, signal});
      ws.current.subs.add(sub);
      signal.addEventListener('abort', () => {
        ws.current.subs.delete(sub);
      });
      if (ws.current.loaded) {
        registerHandlers(ws.current.socket, sub);
      }
    },
    [ws],
  );

  const res = useMemo(
    () => ({
      name,
      send,
      sendChan,
      sub,
      subChan,
    }),
    [name, send, sendChan, sub, subChan],
  );
  return res;
};

const useWSSub = (sub, {onopen, onmessage, onerror, onclose} = {}) => {
  useEffect(() => {
    const controller = new AbortController();
    sub({onopen, onmessage, onerror, onclose}, controller.signal);
    return () => {
      controller.abort();
    };
  }, [sub, onopen, onmessage, onerror, onclose]);
};

const useWSSubChan = (
  sub,
  chan,
  {onopen, onmessage, onerror, onclose} = {},
) => {
  useEffect(() => {
    const controller = new AbortController();
    sub(chan, {onopen, onmessage, onerror, onclose}, controller.signal);
    return () => {
      controller.abort();
    };
  }, [sub, chan, onopen, onmessage, onerror, onclose]);
};

const CTL_CHANNEL = '_ctl_';

const useWSPresenceLocation = (name, send, loc) => {
  const {open} = useWSValue(name);
  useEffect(() => {
    if (!open) {
      return;
    }
    send(CTL_CHANNEL, {
      ops: [{op: 'location', args: {location: loc}}],
    });
  }, [open, send, loc]);
};

export {
  WS_PROTOCOL,
  WSDefaultOpts,
  WSCtx,
  WSState,
  WSProvider,
  useWSValue,
  useWSValueCtx,
  useWS,
  useWSSub,
  useWSSubChan,
  useWSPresenceLocation,
};
<commit_msg>Fix ws retry reset delay<commit_after>import {
  createContext,
  useEffect,
  useCallback,
  useMemo,
  useRef,
  useContext,
} from 'react';
import {atomFamily, useRecoilValue, useSetRecoilState} from 'recoil';

import {sleep} from '../utility';

const WS_PROTOCOL = 'xorkevin.dev-governor_ws_v1alpha1';

const noop = Object.freeze(() => {});

const parseJSON = (s) => {
  try {
    return JSON.parse(s);
  } catch (_err) {
    return {};
  }
};

const WSDefaultOpts = Object.freeze({
  name: '__DEFAULT__',
  send: noop,
  sub: noop,
});

const WSCtx = createContext(WSDefaultOpts);

const defaultWSState = Object.freeze({
  open: false,
});

const WSState = atomFamily({
  key: 'govui:ws_state',
  default: defaultWSState,
});

const WSProvider = ({value, children}) => {
  return <WSCtx.Provider value={value}>{children}</WSCtx.Provider>;
};

const useWSValue = (name) => {
  return useRecoilValue(WSState(name));
};

const useWSValueCtx = () => {
  const {name} = useContext(WSCtx);
  return useWSValue(name);
};

const registerHandlers = (socket, sub) => {
  if (!sub) {
    return;
  }
  const {onopen, onmessage, onerror, onclose, signal} = sub;
  if (onopen) {
    socket.addEventListener('open', onopen, {signal});
  }
  if (onmessage) {
    socket.addEventListener('message', onmessage, {signal});
  }
  if (onerror) {
    socket.addEventListener('error', onerror, {signal});
  }
  if (onclose) {
    socket.addEventListener('close', onclose, {signal});
  }
};

const useWS = (
  name,
  url,
  {delayMin, delayMax, delayExp, prehook, errhook} = {},
) => {
  const setWSState = useSetRecoilState(WSState(name));

  const ws = useRef({
    socket: null,
    open: false,
    loaded: false,
    subs: new Set(),
  });

  if (!url) {
    ws.current.open = false;
  }

  if (typeof delayMin !== 'number') {
    delayMin = 250;
  }
  if (typeof delayMax !== 'number') {
    delayMax = 15000;
  }
  if (typeof delayExp !== 'number') {
    delayExp = 2;
  }

  useEffect(() => {
    ws.current.open = false;
    ws.current.loaded = false;
    setWSState({open: false});
    if (!url) {
      return;
    }
    const controller = new AbortController();
    const signal = controller.signal;
    (async () => {
      let delay = delayMin;
      // eslint-disable-next-line no-constant-condition
      while (true) {
        ws.current.open = false;
        ws.current.loaded = false;
        setWSState({open: false});

        if (prehook) {
          const err = await prehook({signal});
          if (signal.aborted) {
            return;
          }
          if (err) {
            if (errhook) {
              errhook('prehook', err);
            }
            await sleep(delay);
            if (signal.aborted) {
              return;
            }
            delay = Math.min(delay * delayExp, delayMax);
            continue;
          }
        }

        const socket = new WebSocket(url, WS_PROTOCOL);
        const socketClosed = new Promise((resolve) => {
          socket.addEventListener('close', () => {
            if (signal.aborted) {
              resolve();
              return;
            }
            ws.current.open = false;
            ws.current.loaded = false;
            setWSState({open: false});
            resolve();
          });
        });
        socket.addEventListener('open', () => {
          if (signal.aborted) {
            return;
          }
          ws.current.open = true;
          setWSState({open: true});
        });
        const innerController = new AbortController();
        signal.addEventListener(
          'abort',
          () => {
            socket.close(1000, 'OK');
          },
          {signal: innerController.signal},
        );
        for (const sub of ws.current.subs.values()) {
          registerHandlers(socket, sub);
        }
        ws.current.socket = socket;
        ws.current.loaded = true;
        const interval = setInterval(() => {
          delay = delayMin;
        }, delayMax + delayMin);
        await socketClosed;
        clearInterval(interval);
        if (signal.aborted) {
          return;
        }
        innerController.abort();
        await sleep(delay);
        if (signal.aborted) {
          return;
        }
        delay = Math.min(delay * delayExp, delayMax);
      }
    })();
    return () => {
      controller.abort();
    };
  }, [setWSState, ws, url, delayMin, delayMax, delayExp, prehook, errhook]);

  const send = useCallback(
    (data) => {
      if (!ws.current.open) {
        errhook('send', {message: 'Not connected'});
        return;
      }
      ws.current.socket.send(data);
    },
    [ws, errhook],
  );

  const sendChan = useCallback(
    (channel, value) => {
      if (!ws.current.open) {
        errhook('send', {message: 'Not connected'});
        return;
      }
      ws.current.socket.send(
        JSON.stringify({
          channel,
          value,
        }),
      );
    },
    [ws, errhook],
  );

  const sub = useCallback(
    (f, signal) => {
      if (!f || signal.aborted) {
        return;
      }
      const sub = Object.assign({}, f, {signal});
      ws.current.subs.add(sub);
      signal.addEventListener('abort', () => {
        ws.current.subs.delete(sub);
      });
      if (ws.current.loaded) {
        registerHandlers(ws.current.socket, sub);
      }
    },
    [ws],
  );

  const subChan = useCallback(
    (chan, f, signal) => {
      if (!f || signal.aborted) {
        return;
      }
      let onmessage = f.onmessage;
      if (f.onmessage) {
        const isChanPrefix = typeof chan === 'string';
        onmessage = (e) => {
          const data = parseJSON(e.data);
          if (data === undefined || data === null) {
            return;
          }
          const {channel, value} = data;
          if (typeof channel !== 'string') {
            return;
          }
          if (isChanPrefix) {
            if (!channel.startsWith(chan)) {
              return;
            }
          } else {
            if (!chan.test(channel)) {
              return;
            }
          }
          f.onmessage(channel, value, e);
        };
      }
      const sub = Object.assign({}, f, {onmessage, signal});
      ws.current.subs.add(sub);
      signal.addEventListener('abort', () => {
        ws.current.subs.delete(sub);
      });
      if (ws.current.loaded) {
        registerHandlers(ws.current.socket, sub);
      }
    },
    [ws],
  );

  const res = useMemo(
    () => ({
      name,
      send,
      sendChan,
      sub,
      subChan,
    }),
    [name, send, sendChan, sub, subChan],
  );
  return res;
};

const useWSSub = (sub, {onopen, onmessage, onerror, onclose} = {}) => {
  useEffect(() => {
    const controller = new AbortController();
    sub({onopen, onmessage, onerror, onclose}, controller.signal);
    return () => {
      controller.abort();
    };
  }, [sub, onopen, onmessage, onerror, onclose]);
};

const useWSSubChan = (
  sub,
  chan,
  {onopen, onmessage, onerror, onclose} = {},
) => {
  useEffect(() => {
    const controller = new AbortController();
    sub(chan, {onopen, onmessage, onerror, onclose}, controller.signal);
    return () => {
      controller.abort();
    };
  }, [sub, chan, onopen, onmessage, onerror, onclose]);
};

const CTL_CHANNEL = '_ctl_';

const useWSPresenceLocation = (name, send, loc) => {
  const {open} = useWSValue(name);
  useEffect(() => {
    if (!open) {
      return;
    }
    send(CTL_CHANNEL, {
      ops: [{op: 'location', args: {location: loc}}],
    });
  }, [open, send, loc]);
};

export {
  WS_PROTOCOL,
  WSDefaultOpts,
  WSCtx,
  WSState,
  WSProvider,
  useWSValue,
  useWSValueCtx,
  useWS,
  useWSSub,
  useWSSubChan,
  useWSPresenceLocation,
};
<|endoftext|>


<commit_before>/*jshint node:true*/

var path          = require('path');
var testInfo      = require('ember-cli-test-info');
var stringUtil    = require('ember-cli-string-utils');
var getPathOption = require('../../lib/utilities/get-component-path-option');

module.exports = {
  description: 'Generates a component integration or unit test.',

  availableOptions: [
    {
      name: 'test-type',
      type: ['integration', 'unit'],
      default: 'integration',
      aliases:[
        { 'i': 'integration'},
        { 'u': 'unit'},
        { 'integration': 'integration' },
        { 'unit': 'unit' }
      ]
    }
  ],

  fileMapTokens: function() {
    return {
      __testType__: function(options) {
        return options.locals.testType || 'integration';
      },
      __path__: function(options) {
        if (options.pod) {
          return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
        }
        return 'components';
      }
    };
  },
  locals: function(options) {
    var dasherizedModuleName = stringUtil.dasherize(options.entity.name);
    var componentPathName = dasherizedModuleName;
    var testType = options.testType || "integration";
    var friendlyTestDescription = testInfo.description(options.entity.name, "Integration", "Component");

    if (options.pod && options.path !== 'components' && options.path !== '') {
      componentPathName = [options.path, dasherizedModuleName].join('/');
    }

    if (options.testType === 'unit') {
      friendlyTestDescription = testInfo.description(options.entity.name, "Unit", "Component");
    }

    return {
      path: getPathOption(options),
      testType: testType,
      componentPathName: componentPathName,
      friendlyTestDescription: friendlyTestDescription
    };
  }
};
<commit_msg>Auto merge of #5098 - drspaniel:install-inline-precompiler, r=rwjblue<commit_after>/*jshint node:true*/

var path          = require('path');
var testInfo      = require('ember-cli-test-info');
var stringUtil    = require('ember-cli-string-utils');
var isPackageMissing = require('ember-cli-is-package-missing');
var getPathOption = require('../../lib/utilities/get-component-path-option');

module.exports = {
  description: 'Generates a component integration or unit test.',

  availableOptions: [
    {
      name: 'test-type',
      type: ['integration', 'unit'],
      default: 'integration',
      aliases:[
        { 'i': 'integration'},
        { 'u': 'unit'},
        { 'integration': 'integration' },
        { 'unit': 'unit' }
      ]
    }
  ],

  fileMapTokens: function() {
    return {
      __testType__: function(options) {
        return options.locals.testType || 'integration';
      },
      __path__: function(options) {
        if (options.pod) {
          return path.join(options.podPath, options.locals.path, options.dasherizedModuleName);
        }
        return 'components';
      }
    };
  },
  locals: function(options) {
    var dasherizedModuleName = stringUtil.dasherize(options.entity.name);
    var componentPathName = dasherizedModuleName;
    var testType = options.testType || "integration";
    var friendlyTestDescription = testInfo.description(options.entity.name, "Integration", "Component");

    if (options.pod && options.path !== 'components' && options.path !== '') {
      componentPathName = [options.path, dasherizedModuleName].join('/');
    }

    if (options.testType === 'unit') {
      friendlyTestDescription = testInfo.description(options.entity.name, "Unit", "Component");
    }

    return {
      path: getPathOption(options),
      testType: testType,
      componentPathName: componentPathName,
      friendlyTestDescription: friendlyTestDescription
    };
  },
  afterInstall: function(options) {
    if (!options.dryRun && options.testType === 'integration' && isPackageMissing(this, 'ember-cli-htmlbars-inline-precompile')) {
      return this.addPackagesToProject([
        { name: 'ember-cli-htmlbars-inline-precompile', target: '^0.3.1' }
      ]);
    }
  }
};
<|endoftext|>


<commit_before>describe('kalk.Calculator', function() {
    describe('buffer', function() {
        it('should initialize with 0 as the first entry', function() {
            var calc = new kalk.Calculator();

            expect(calc.buffer[0]).toBe(0);
        });
    });

    describe('add', function() {
        it('should calculate the sum of two positive operands', function() {
            var calc = new kalk.Calculator();
            expect(calc.add(4, 8)).toEqual(12);
        });

        it('should calculate sum given a decimal operand', function() {
            var calc = new kalk.Calculator();
            expect(calc.add(4.5, 8.1)).toEqual(12.6);
        });

        it('should calculate sum given a negative operand', function() {
            var calc = new kalk.Calculator();
            expect(calc.add(-4, 8)).toEqual(4);
        });
    });

    describe('sub', function() {
        // not specced out with as much detail as "add"
        it('should calculate the difference of two operands, subtracting the rhs value from the lhs value', function() {
            var calc = new kalk.Calculator();
            expect(calc.sub(15, 8)).toEqual(7);
        });
    });

    describe('mult', function() {
        // not specced out with as much detail as "add"
        it('should calculate the product of two operands', function() {
            var calc = new kalk.Calculator();
            expect(calc.mult(3, 5)).toEqual(15);
        });
    });

    describe('div', function() {
        // not specced out with as much detail as "add"
        it('should calculate the result of dividing the lhs operand by the rhs operand', function() {
            var calc = new kalk.Calculator();
            expect(calc.div(25, 5)).toEqual(5);
        });
    });

    describe('getOp', function() {
        it('should yield an add function given a "+" operator', function() {
            var calc = new kalk.Calculator();

            op = calc.getOp('+');

            expect(op).toBe(calc.add);
            expect(op(10, 23)).toEqual(33);
        });

        it('should yield a sub function given a "-" operator', function() {
            var calc = new kalk.Calculator();

            op = calc.getOp('-');

            expect(op).toBe(calc.sub);
            expect(op(45, 25)).toEqual(20);
        });

        it('should yield a prod function given a "*" operator', function() {
            var calc = new kalk.Calculator();

            op = calc.getOp('*');

            expect(op).toBe(calc.mult);
            expect(op(10, 8)).toEqual(80);
        });

        it('should yield a div function given a "/" operator', function() {
            var calc = new kalk.Calculator();

            op = calc.getOp('/');

            expect(op).toBe(calc.div);
            expect(op(55, 11)).toEqual(5);
        });
    });

    describe('input', function() {
        var calc;

        beforeEach(function() {
            calc = new kalk.Calculator();
        });

        it('should initialize with a "lhs", "rhs" and "result" set to 0', function() {
            expect(calc.lhs).toBe(0);
            expect(calc.rhs).toBe(0);
            expect(calc.result).toBe(0);
        });

        it('should accept regular numbers', function() {
            expect(function() {
                 calc.input(3);
            }).not.toThrow();
        });

        it('should accept "stringified" numbers', function() {
            expect(function() {
                 calc.input('3');
            }).not.toThrow();
        });

        it('should accept + as a valid operation', function() {
            expect(function() {
                 calc.input('+');
            }).not.toThrow();
        });

        it('should accept - as a valid operation', function() {
            expect(function() {
                 calc.input('-');
            }).not.toThrow();
        });

        it('should accept / as a valid operation', function() {
            expect(function() {
                 calc.input('/');
            }).not.toThrow();
        });

        it('should accept * as a valid operation', function() {
            expect(function() {
                 calc.input('*');
            }).not.toThrow();
        });

        xit('should accept = as a valid operation', function() {
            expect(function() {
                 calc.input('=');
            }).not.toThrow();
        });

        it('should fail on any non-numeric and non-valid operation', function() {
            expect(function() {
                 calc.input('r');
            }).toThrow('Invalid input. "r" is not a number or a valid operation');
        });

        it('should overwrite the last buffer entry if it is a number and the new input is also a number', function() {
            expect(calc.buffer[0]).toBe(0);

            calc.input(5);
            expect(calc.buffer[0]).toBe(5);
            calc.input(14);

            expect(calc.buffer[0]).toBe(14);
            expect(calc.buffer.length).toBe(1);
        });

        it('should push an operation into the buffer if the last entry is a number', function() {
            calc.input(7);

            calc.input('+');

            expect(calc.buffer.length).toBe(2);
            expect(calc.buffer[1]).toBe('+');
        });

        it('should push a number into the buffer if the last entry is not a number', function() {
            calc.input(50);
            calc.input('-');
            calc.input(10);

            expect(calc.buffer.length).toBe(3);
            expect(calc.buffer[2]).toBe(10);
        });

        it('should calculate the result of the expression in the buffer given the "=" operation', function() {
            calc.input(25);
            calc.input('+');
            calc.input(15);

            calc.input('=');

            expect(calc.result).toBe(40);
        });
    });

    xdescribe('add', function() {
        it('should calculate the sum of the given operands', function() {
            var calc = new kalk.Calculator();

            calc.input(5);
            calc.input('+')
            calc.input(4);
            calc.input('=');

            expect(calc.result).toEqual(9);
        });
    });
});<commit_msg>Refactored kalk example specs for clarity.<commit_after>describe('kalk.Calculator', function() {
    describe('When instantiated', function() {
        it('should initialize "buffer" with 0 as the first entry', function() {
            var calc = new kalk.Calculator();

            expect(calc.buffer[0]).toBe(0);
        });

        it('should initialize "lhs", "rhs" and "result" to 0', function() {
            var calc = new kalk.Calculator();

            expect(calc.lhs).toBe(0);
            expect(calc.rhs).toBe(0);
            expect(calc.result).toBe(0);
        });
    });

    describe('add', function() {
        var calc;

        beforeEach(function() {
            calc = new kalk.Calculator();
        });

        it('should calculate the sum of two positive operands', function() {
            expect(calc.add(4, 8)).toEqual(12);
        });

        it('should calculate sum given a decimal operand', function() {
            expect(calc.add(4.5, 8.1)).toEqual(12.6);
        });

        it('should calculate sum given a negative operand', function() {
            expect(calc.add(-4, 8)).toEqual(4);
        });
    });

    describe('sub', function() {
        // not specced out with as much detail as "add"
        it('should calculate the difference of two operands, subtracting the rhs value from the lhs value', function() {
            var calc = new kalk.Calculator();
            expect(calc.sub(15, 8)).toEqual(7);
        });
    });

    describe('mult', function() {
        // not specced out with as much detail as "add"
        it('should calculate the product of two operands', function() {
            var calc = new kalk.Calculator();
            expect(calc.mult(3, 5)).toEqual(15);
        });
    });

    describe('div', function() {
        // not specced out with as much detail as "add"
        it('should calculate the result of dividing the lhs operand by the rhs operand', function() {
            var calc = new kalk.Calculator();
            expect(calc.div(25, 5)).toEqual(5);
        });
    });

    describe('getOp', function() {
        var calc;

        beforeEach(function() {
            calc = new kalk.Calculator();
        });

        it('should yield an add function given a "+" operator', function() {
            op = calc.getOp('+');

            expect(op).toBe(calc.add);
            expect(op(10, 23)).toEqual(33);
        });

        it('should yield a sub function given a "-" operator', function() {
            op = calc.getOp('-');

            expect(op).toBe(calc.sub);
            expect(op(45, 25)).toEqual(20);
        });

        it('should yield a prod function given a "*" operator', function() {
            op = calc.getOp('*');

            expect(op).toBe(calc.mult);
            expect(op(10, 8)).toEqual(80);
        });

        it('should yield a div function given a "/" operator', function() {
            op = calc.getOp('/');

            expect(op).toBe(calc.div);
            expect(op(55, 11)).toEqual(5);
        });
    });

    describe('input', function() {
        var calc;

        beforeEach(function() {
            calc = new kalk.Calculator();
        });

        it('should accept regular numbers', function() {
            expect(function() {
                 calc.input(3);
            }).not.toThrow();
        });

        it('should accept "stringified" numbers', function() {
            expect(function() {
                 calc.input('3');
            }).not.toThrow();
        });

        it('should accept + as a valid operation', function() {
            expect(function() {
                 calc.input('+');
            }).not.toThrow();
        });

        it('should accept - as a valid operation', function() {
            expect(function() {
                 calc.input('-');
            }).not.toThrow();
        });

        it('should accept / as a valid operation', function() {
            expect(function() {
                 calc.input('/');
            }).not.toThrow();
        });

        it('should accept * as a valid operation', function() {
            expect(function() {
                 calc.input('*');
            }).not.toThrow();
        });

        xit('should accept = as a valid operation', function() {
            expect(function() {
                 calc.input('=');
            }).not.toThrow();
        });

        it('should fail on any non-numeric and non-valid operation', function() {
            expect(function() {
                 calc.input('r');
            }).toThrow('Invalid input. "r" is not a number or a valid operation');
        });

        it('should overwrite the last buffer entry if it is a number and the new input is also a number', function() {
            expect(calc.buffer[0]).toBe(0);

            calc.input(5);
            expect(calc.buffer[0]).toBe(5);
            calc.input(14);

            expect(calc.buffer[0]).toBe(14);
            expect(calc.buffer.length).toBe(1);
        });

        it('should push an operation into the buffer if the last entry is a number', function() {
            calc.input(7);

            calc.input('+');

            expect(calc.buffer.length).toBe(2);
            expect(calc.buffer[1]).toBe('+');
        });

        it('should push a number into the buffer if the last entry is not a number', function() {
            calc.input(50);
            calc.input('-');
            calc.input(10);

            expect(calc.buffer.length).toBe(3);
            expect(calc.buffer[2]).toBe(10);
        });

        it('should calculate the result of the expression in the buffer given the "=" operation', function() {
            calc.input(25);
            calc.input('+');
            calc.input(15);

            calc.input('=');

            expect(calc.result).toBe(40);
        });
    });

    xdescribe('add', function() {
        it('should calculate the sum of the given operands', function() {
            var calc = new kalk.Calculator();

            calc.input(5);
            calc.input('+')
            calc.input(4);
            calc.input('=');

            expect(calc.result).toEqual(9);
        });
    });
});<|endoftext|>


<commit_before>import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import api from '../steemAPI';
import * as postActions from './postActions';
import { closePostModal } from '../actions';
import PostSingleModal from './PostSingleModal';
import PostSinglePage from './PostSinglePage';
import * as reblogActions from '../app/Reblog/reblogActions';
import * as commentsActions from '../comments/commentsActions';
import * as bookmarkActions from '../bookmarks/bookmarksActions';

@connect(
  ({ posts, app, reblog, auth, bookmarks }) => ({
    content: posts[app.lastPostId] ? posts[app.lastPostId] : {},
    isPostModalOpen: app.isPostModalOpen,
    lastPostId: app.lastPostId,
    sidebarIsVisible: app.sidebarIsVisible,
    reblogList: reblog,
    bookmarks,
    auth,
  }),
  (dispatch, ownProps) => bindActionCreators({
    reblog: reblogActions.reblog,
    closePostModal: closePostModal,
    getContent: () => postActions.getContent(
      ownProps.params.author,
      ownProps.params.permlink
    ),
    openCommentingDraft: commentsActions.openCommentingDraft,
    closeCommentingDraft: commentsActions.closeCommentingDraft,
    likePost: id => postActions.votePost(id),
    unlikePost: id => postActions.votePost(id, 0),
    dislikePost: id => postActions.votePost(id, -1000),
    toggleBookmark: bookmarkActions.toggleBookmark,
  }, dispatch)
)
export default class PostSingle extends React.Component {
  constructor(props) {
    super(props);
  }

  componentWillMount() {
    if (!this.props.modal) {
      this.props.getContent();
    }
  }

  handlePageClick(e) {
    e.stopPropagation();
    this.props.closeCommentingDraft();
  }

  render() {
    const { modal, isPostModalOpen, sidebarIsVisible, content, reblog, reblogList, auth } = this.props;
    const isPostLiked =
      auth.isAuthenticated &&
      content.active_votes &&
      content.active_votes.some(vote => vote.voter === auth.user.name && vote.percent > 0);

    const isPostDisliked =
      auth.isAuthenticated &&
      content.active_votes &&
      content.active_votes.some(vote => vote.voter === auth.user.name && vote.percent < 0);

    const openCommentingDraft = () => this.props.openCommentingDraft({
      parentAuthor: content.author,
      parentPermlink: content.permlink,
      category: content.category,
      id: content.id,
    });

    return (

 this.handlePageClick(e)}>
        { (modal && isPostModalOpen) &&
          <PostSingleModal
            content={content}
            sidebarIsVisible={sidebarIsVisible}
            closePostModal={this.props.closePostModal}
            route={this.props.route}
            reblog={() => reblog(content.id)}
            isReblogged={reblogList.includes(content.id)}
            openCommentingDraft={openCommentingDraft}
            likePost={() => this.props.likePost(content.id)}
            unlikePost={() => this.props.unlikePost(content.id)}
            dislikePost={() => this.props.dislikePost(content.id)}
            isPostLiked={isPostLiked}
            isPostDisliked={isPostDisliked}
            bookmarks={this.props.bookmarks}
            toggleBookmark={this.props.toggleBookmark}
          />
        }

        { (!modal && content.author) &&
          <PostSinglePage
            content={content}
            reblog={() => reblog(content.id)}
            isReblogged={reblogList.includes(content.id)}
            openCommentingDraft={openCommentingDraft}
            likePost={() => this.props.likePost(content.id)}
            unlikePost={() => this.props.unlikePost(content.id)}
            dislikePost={() => this.props.dislikePost(content.id)}
            isPostLiked={isPostLiked}
            isPostDisliked={isPostDisliked}
            bookmarks={this.props.bookmarks}
            toggleBookmark={this.props.toggleBookmark}
          />
        }

    );
  }
}
<commit_msg>early exit if content is not available<commit_after>import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import api from '../steemAPI';
import * as postActions from './postActions';
import { closePostModal } from '../actions';
import PostSingleModal from './PostSingleModal';
import PostSinglePage from './PostSinglePage';
import * as reblogActions from '../app/Reblog/reblogActions';
import * as commentsActions from '../comments/commentsActions';
import * as bookmarkActions from '../bookmarks/bookmarksActions';

@connect(
  ({ posts, app, reblog, auth, bookmarks }) => ({
    content: posts[app.lastPostId] ? posts[app.lastPostId] : null,
    isPostModalOpen: app.isPostModalOpen,
    lastPostId: app.lastPostId,
    sidebarIsVisible: app.sidebarIsVisible,
    reblogList: reblog,
    bookmarks,
    auth,
  }),
  (dispatch, ownProps) => bindActionCreators({
    reblog: reblogActions.reblog,
    closePostModal: closePostModal,
    getContent: () => postActions.getContent(
      ownProps.params.author,
      ownProps.params.permlink
    ),
    openCommentingDraft: commentsActions.openCommentingDraft,
    closeCommentingDraft: commentsActions.closeCommentingDraft,
    likePost: id => postActions.votePost(id),
    unlikePost: id => postActions.votePost(id, 0),
    dislikePost: id => postActions.votePost(id, -1000),
    toggleBookmark: bookmarkActions.toggleBookmark,
  }, dispatch)
)
export default class PostSingle extends React.Component {
  constructor(props) {
    super(props);
  }

  componentWillMount() {
    if (!this.props.modal) {
      this.props.getContent();
    }
  }

  handlePageClick(e) {
    e.stopPropagation();
    this.props.closeCommentingDraft();
  }

  render() {
    const { modal, isPostModalOpen, sidebarIsVisible, content, reblog, reblogList, auth } = this.props;

    if (!content) {
      return null;
    }

    const isPostLiked =
      auth.isAuthenticated &&
      content.active_votes &&
      content.active_votes.some(vote => vote.voter === auth.user.name && vote.percent > 0);

    const isPostDisliked =
      auth.isAuthenticated &&
      content.active_votes &&
      content.active_votes.some(vote => vote.voter === auth.user.name && vote.percent < 0);

    const openCommentingDraft = () => this.props.openCommentingDraft({
      parentAuthor: content.author,
      parentPermlink: content.permlink,
      category: content.category,
      id: content.id,
    });

    return (

 this.handlePageClick(e)}>
        { (modal && isPostModalOpen) &&
          <PostSingleModal
            content={content}
            sidebarIsVisible={sidebarIsVisible}
            closePostModal={this.props.closePostModal}
            route={this.props.route}
            reblog={() => reblog(content.id)}
            isReblogged={reblogList.includes(content.id)}
            openCommentingDraft={openCommentingDraft}
            likePost={() => this.props.likePost(content.id)}
            unlikePost={() => this.props.unlikePost(content.id)}
            dislikePost={() => this.props.dislikePost(content.id)}
            isPostLiked={isPostLiked}
            isPostDisliked={isPostDisliked}
            bookmarks={this.props.bookmarks}
            toggleBookmark={this.props.toggleBookmark}
          />
        }

        { (!modal && content.author) &&
          <PostSinglePage
            content={content}
            reblog={() => reblog(content.id)}
            isReblogged={reblogList.includes(content.id)}
            openCommentingDraft={openCommentingDraft}
            likePost={() => this.props.likePost(content.id)}
            unlikePost={() => this.props.unlikePost(content.id)}
            dislikePost={() => this.props.dislikePost(content.id)}
            isPostLiked={isPostLiked}
            isPostDisliked={isPostDisliked}
            bookmarks={this.props.bookmarks}
            toggleBookmark={this.props.toggleBookmark}
          />
        }

    );
  }
}
<|endoftext|>


<commit_before>
var BufferedProcess = require('atom').BufferedProcess;
var StatusView = require('./status-view')

module.exports = {
  timeout : null,
  numberOfInstaledPackage: 0,
  numberOfPackagedToBeInstalled: 0,
  numberOfSucessfullyInstalled: 0,
  loadPackageList: function(packageListName) {
      var gistID;
      switch (packageListName) {
        case 'PHP':
          gistID = '4157065edd53fdd3daca';
        break;
        case 'Javascript':
          gistID = 'da9b00c4ddf35d9648b4';
        case 'General':
          gistID = '2b7e68af24295502fe28';
        case 'Git':
          gistID = 'c1cf7bcd42a0478c9347';
        break;
      }

      this.loadPackageListFromGIst(gistID);
  },

  loadPackageListFromGIst: function(gistID) {
    var request = require('request');
    var requestOptions = {
      url: 'https://api.github.com/gists/' + gistID,
      headers: {
        'User-Agent': 'Trudko'
      }
    }

    var that = this;
    var wasListLoaded;
    request(requestOptions, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var responseObject = JSON.parse(body);
        var packageList = responseObject.files['gistfile1.txt'].content;
        packageList = packageList.split(',');
        var availablePackages = atom.packages.getAvailablePackageNames()
        packageList = packageList.filter(function(packageName) {
          packageName = packageName.trim();
          return availablePackages.indexOf(packageName) < 0;
        });
        var PackageListPackagesView  = require('./package-list-packages-view');
        if (packageList.length > 0) {
          new PackageListPackagesView(packageList);
        } else {
          new StatusView({type: 'text-warning', message: 'All packages from the list are already installed!'})
        }
        wasListLoaded = true;
      } else if (response.statusCode == 404) {
          new StatusView({type: 'text-warning', message: 'Gist with id ' + gistID + ' was not found!'})
          wasListLoaded = false;
      }
    });

    return wasListLoaded;
  },

  installPackageList: function(packageList) {
    var that = this;
    this.numberOfPackagedToBeInstalled = packageList.length;
    packageList.forEach(function(package) {
      that.installPackage(package);
    });
  },

  installPackage: function(packageName) {
      var args, command, exit, stderr, stdout;
      command = atom.packages.getApmPath();
      args = ['install', packageName];

      var that = this;

      stdout = function(output) {console.log(output)};
      stderr = function(output) {console.log(output)};
      exit = (function(_this) {
        return function(exitCode) {
          if (exitCode === 0) {
             that.numberOfSucessfullyInstalled++;
          } else {
            new StatusView({type: 'text-error', message: "" + packageName + "An error occurred installing! Please see console log."})
          }
          that.numberOfInstaledPackage++;
          that.updateInstalledPackageCounter();
        };
      })(this);
      this.currentInstall = new BufferedProcess({
        command: command,
        args: args,
        stdout: stdout,
        stderr: stderr,
        exit: exit
      });
  },
  updateInstalledPackageCounter: function() {
    if (this.numberOfInstaledPackage === this.numberOfPackagedToBeInstalled) {
      if (this.numberOfInstaledPackage === this.numberOfSucessfullyInstalled) {
        new StatusView({type: 'text-warning', message: 'All packages were installed succesfully'})
      }
      this.numberOfInstaledPackage = 0;
      this.numberOfPackagedToBeInstalled = 0;
      this.numberOfSucessfullyInstalled = 0;
    }
  }
}
<commit_msg>Changed color of message after successful download of all packages<commit_after>
var BufferedProcess = require('atom').BufferedProcess;
var StatusView = require('./status-view')

module.exports = {
  timeout : null,
  numberOfInstaledPackage: 0,
  numberOfPackagedToBeInstalled: 0,
  numberOfSucessfullyInstalled: 0,
  loadPackageList: function(packageListName) {
      var gistID;
      switch (packageListName) {
        case 'PHP':
          gistID = '4157065edd53fdd3daca';
        break;
        case 'Javascript':
          gistID = 'da9b00c4ddf35d9648b4';
        case 'General':
          gistID = '2b7e68af24295502fe28';
        case 'Git':
          gistID = 'c1cf7bcd42a0478c9347';
        break;
      }

      this.loadPackageListFromGIst(gistID);
  },

  loadPackageListFromGIst: function(gistID) {
    var request = require('request');
    var requestOptions = {
      url: 'https://api.github.com/gists/' + gistID,
      headers: {
        'User-Agent': 'Trudko'
      }
    }

    var that = this;
    var wasListLoaded;
    request(requestOptions, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        var responseObject = JSON.parse(body);
        var packageList = responseObject.files['gistfile1.txt'].content;
        packageList = packageList.split(',');
        var availablePackages = atom.packages.getAvailablePackageNames()
        packageList = packageList.filter(function(packageName) {
          packageName = packageName.trim();
          return availablePackages.indexOf(packageName) < 0;
        });
        var PackageListPackagesView  = require('./package-list-packages-view');
        if (packageList.length > 0) {
          new PackageListPackagesView(packageList);
        } else {
          new StatusView({type: 'text-warning', message: 'All packages from the list are already installed!'})
        }
        wasListLoaded = true;
      } else if (response.statusCode == 404) {
          new StatusView({type: 'text-warning', message: 'Gist with id ' + gistID + ' was not found!'})
          wasListLoaded = false;
      }
    });

    return wasListLoaded;
  },

  installPackageList: function(packageList) {
    var that = this;
    this.numberOfPackagedToBeInstalled = packageList.length;
    packageList.forEach(function(package) {
      that.installPackage(package);
    });
  },

  installPackage: function(packageName) {
      var args, command, exit, stderr, stdout;
      command = atom.packages.getApmPath();
      args = ['install', packageName];

      var that = this;

      stdout = function(output) {console.log(output)};
      stderr = function(output) {console.log(output)};
      exit = (function(_this) {
        return function(exitCode) {
          if (exitCode === 0) {
             that.numberOfSucessfullyInstalled++;
          } else {
            new StatusView({type: 'text-error', message: "" + packageName + "An error occurred installing! Please see console log."})
          }
          that.numberOfInstaledPackage++;
          that.updateInstalledPackageCounter();
        };
      })(this);
      this.currentInstall = new BufferedProcess({
        command: command,
        args: args,
        stdout: stdout,
        stderr: stderr,
        exit: exit
      });
  },
  updateInstalledPackageCounter: function() {
    if (this.numberOfInstaledPackage === this.numberOfPackagedToBeInstalled) {
      if (this.numberOfInstaledPackage === this.numberOfSucessfullyInstalled) {
        new StatusView({type: 'text-success', message: 'All packages were installed succesfully'})
      }
      this.numberOfInstaledPackage = 0;
      this.numberOfPackagedToBeInstalled = 0;
      this.numberOfSucessfullyInstalled = 0;
    }
  }
}
<|endoftext|>


<commit_before>module.exports = {
  babelrc: false,
  presets: [
    // webpack can resolve ES6 modules, so disable commonjs modules
    [require.resolve('babel-preset-env'), { modules: false }],
    require.resolve('babel-preset-react'),
    require.resolve('babel-preset-stage-2'),
  ],
  plugins: [
    // TODO - Verify that we don't need babel-plugin-transform-runtime anymore
    // require.resolve("babel-plugin-transform-runtime")
  ],
};
<commit_msg>Add babel-plugin-styled-components<commit_after>module.exports = {
  babelrc: false,
  presets: [
    // webpack can resolve ES6 modules, so disable commonjs modules
    [require.resolve('babel-preset-env'), { modules: false }],
    require.resolve('babel-preset-react'),
    require.resolve('babel-preset-stage-2'),
  ],
  plugins: [
    [require.resolve('babel-plugin-styled-components'), { ssr: true }],
    // TODO - Verify that we don't need babel-plugin-transform-runtime anymore
    // require.resolve("babel-plugin-transform-runtime")
  ],
};
<|endoftext|>


<commit_before>'use strict'

RoomPosition.prototype.getAdjacent = function () {
  const results = []
  const room = Game.rooms[this.roomName]

  // Row -1
  if (this.y - 1 >= 0) {
    if (this.x - 1 >= 0) {
      results.push(room.getPositionAt(this.x - 1, this.y - 1))
    }
    results.push(room.getPositionAt(this.x, this.y - 1))
    if (this.x + 1 <= 49) {
      results.push(room.getPositionAt(this.x + 1, this.y - 1))
    }
  }

  // Row 0
  if (this.x - 1 >= 0) {
    results.push(room.getPositionAt(this.x - 1, this.y))
  }
  // placeholder for "self"
  if (this.x + 1 <= 49) {
    results.push(room.getPositionAt(this.x + 1, this.y))
  }

  // Row +1
  if (this.y + 1 <= 49) {
    if (this.x - 1 >= 0) {
      results.push(room.getPositionAt(this.x - 1, this.y + 1))
    }
    results.push(room.getPositionAt(this.x, this.y + 1))
    if (this.x + 1 <= 49) {
      results.push(room.getPositionAt(this.x + 1, this.y + 1))
    }
  }

  return results
}

RoomPosition.prototype.getSteppableAdjacent = function (includeCreeps = false) {
  return _.filter(this.getAdjacent(), function (pos) {
    return pos.isSteppable(includeCreeps)
  })
}

RoomPosition.prototype.getAdjacentInRange = function (range = 1) {
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  let positions = []
  for (let x = bounds.left; x <= bounds.right; x++) {
    for (let y = bounds.top; y <= bounds.bottom; y++) {
      positions.push(new RoomPosition(x, y, this.roomName))
    }
  }
  return positions
}

RoomPosition.prototype.getSteppableAdjacentInRange = function (range = 1) {
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  let positions = [],
	position
  for (let x = bounds.left; x <= bounds.right; x++) {
    for (let y = bounds.top; y <= bounds.bottom; y++) {
	  position = new RoomPosition(x, y, this.roomName)
      if (position.isSteppable()) positions.push(position)
    }
  }
  return positions
}

RoomPosition.prototype.isSteppable = function (includeCreeps = false) {
  if (this.getTerrainAt() === 'wall') {
    return false
  }
  const structures = this.lookFor(LOOK_STRUCTURES)
  let structure
  for (structure of structures) {
    if (OBSTACLE_OBJECT_TYPES.indexOf(structure.structureType) >= 0) {
      return false
    }
  }
  if (includeCreeps) {
    if (this.lookFor(LOOK_CREEPS).length > 0) {
      return false
    }
  }
  return true
}

RoomPosition.prototype.getMostOpenNeighbor = function () {
  const steppable = this.getSteppableAdjacent()
  let pos
  let best
  let score = 0
  for (pos of steppable) {
    const posScore = pos.getSteppableAdjacent().length
    if (posScore > score) {
      score = posScore
      best = pos
    }
  }
  return best
}

RoomPosition.prototype.isEdge = function () {
  return this.x === 49 || this.x === 0 || this.y === 49 || this.y === 0
}

RoomPosition.prototype.isExit = function () {
  return this.isEdge() && Game.map.getTerrainAt(this) !== 'wall'
}

RoomPosition.prototype.inFrontOfExit = function () {
  if (this.isEdge()) {
    return false
  }
  const neighbors = this.getAdjacent()
  let neighbor
  for (neighbor of neighbors) {
    if (neighbor.isExit()) {
      return true
    }
  }
  return false
}

RoomPosition.prototype.getTerrainAt = function () {
  return Game.map.getTerrainAt(this)
}

RoomPosition.prototype.getManhattanDistance = function (pos) {
  return Math.abs(this.x - pos.x) + Math.abs(this.y - pos.y)
}

RoomPosition.prototype.serialize = function () {
  return Room.serializeName(this.roomName) + String.fromCharCode(((this.x * 100) + +this.y) + 200)
}

RoomPosition.deserialize = function (string) {
  const roomname = Room.deserializeName(string.slice(0, -1))
  const coordraw = (string.charCodeAt(string.length - 1) - 200)
  const x = Math.floor(coordraw / 100)
  const y = coordraw % 50
  return new RoomPosition(x, y, roomname)
}

RoomPosition.prototype.lookAroundFor = function (type, range = 1) {
  if (!Game.rooms[this.roomName]) {
    return ERR_INVALID_TARGET
  }
  const room = Game.rooms[this.roomName]
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  return room.lookForAtArea(type, bounds.top, bounds.left, bounds.bottom, bounds.right, true)
}

RoomPosition.prototype.lookAround = function (range = 1) {
  if (!Game.rooms[this.roomName]) {
    return ERR_INVALID_TARGET
  }
  const room = Game.rooms[this.roomName]
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  return room.lookAtArea(bounds.top, bounds.left, bounds.bottom, bounds.right, true)
}

/**
 * Creates a bounding box clamped inside the borders of the room
 * @param {number} x position to get bounds-range from
 * @param {number} y position to get bounds-range from
 * @param {number} range of the bounding box
 * @returns {{left: number, right: number, top: number, bottom: number}}
 */
function createBoundingBoxForRange (x, y, range) {
  const absRange = Math.abs(range)
  const left = Math.min(Math.max(x - absRange, 0), 49)
  const right = Math.max(Math.min(x + absRange, 49), 0)
  const top = Math.min(Math.max(y - absRange, 0), 49)
  const bottom = Math.max(Math.min(y + absRange, 49), 0)
  return {left, right, top, bottom}
}

module.exports = {
  createBoundingBoxForRange
}
<commit_msg>Formatting<commit_after>'use strict'

RoomPosition.prototype.getAdjacent = function () {
  const results = []
  const room = Game.rooms[this.roomName]

  // Row -1
  if (this.y - 1 >= 0) {
    if (this.x - 1 >= 0) {
      results.push(room.getPositionAt(this.x - 1, this.y - 1))
    }
    results.push(room.getPositionAt(this.x, this.y - 1))
    if (this.x + 1 <= 49) {
      results.push(room.getPositionAt(this.x + 1, this.y - 1))
    }
  }

  // Row 0
  if (this.x - 1 >= 0) {
    results.push(room.getPositionAt(this.x - 1, this.y))
  }
  // placeholder for "self"
  if (this.x + 1 <= 49) {
    results.push(room.getPositionAt(this.x + 1, this.y))
  }

  // Row +1
  if (this.y + 1 <= 49) {
    if (this.x - 1 >= 0) {
      results.push(room.getPositionAt(this.x - 1, this.y + 1))
    }
    results.push(room.getPositionAt(this.x, this.y + 1))
    if (this.x + 1 <= 49) {
      results.push(room.getPositionAt(this.x + 1, this.y + 1))
    }
  }

  return results
}

RoomPosition.prototype.getSteppableAdjacent = function (includeCreeps = false) {
  return _.filter(this.getAdjacent(), function (pos) {
    return pos.isSteppable(includeCreeps)
  })
}

RoomPosition.prototype.getAdjacentInRange = function (range = 1) {
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  let positions = []
  for (let x = bounds.left; x <= bounds.right; x++) {
    for (let y = bounds.top; y <= bounds.bottom; y++) {
      positions.push(new RoomPosition(x, y, this.roomName))
    }
  }
  return positions
}

RoomPosition.prototype.getSteppableAdjacentInRange = function (range = 1) {
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  let positions = []
  let position
  for (let x = bounds.left; x <= bounds.right; x++) {
    for (let y = bounds.top; y <= bounds.bottom; y++) {
      position = new RoomPosition(x, y, this.roomName)
      if (position.isSteppable()) positions.push(position)
    }
  }
  return positions
}

RoomPosition.prototype.isSteppable = function (includeCreeps = false) {
  if (this.getTerrainAt() === 'wall') {
    return false
  }
  const structures = this.lookFor(LOOK_STRUCTURES)
  let structure
  for (structure of structures) {
    if (OBSTACLE_OBJECT_TYPES.indexOf(structure.structureType) >= 0) {
      return false
    }
  }
  if (includeCreeps) {
    if (this.lookFor(LOOK_CREEPS).length > 0) {
      return false
    }
  }
  return true
}

RoomPosition.prototype.getMostOpenNeighbor = function () {
  const steppable = this.getSteppableAdjacent()
  let pos
  let best
  let score = 0
  for (pos of steppable) {
    const posScore = pos.getSteppableAdjacent().length
    if (posScore > score) {
      score = posScore
      best = pos
    }
  }
  return best
}

RoomPosition.prototype.isEdge = function () {
  return this.x === 49 || this.x === 0 || this.y === 49 || this.y === 0
}

RoomPosition.prototype.isExit = function () {
  return this.isEdge() && Game.map.getTerrainAt(this) !== 'wall'
}

RoomPosition.prototype.inFrontOfExit = function () {
  if (this.isEdge()) {
    return false
  }
  const neighbors = this.getAdjacent()
  let neighbor
  for (neighbor of neighbors) {
    if (neighbor.isExit()) {
      return true
    }
  }
  return false
}

RoomPosition.prototype.getTerrainAt = function () {
  return Game.map.getTerrainAt(this)
}

RoomPosition.prototype.getManhattanDistance = function (pos) {
  return Math.abs(this.x - pos.x) + Math.abs(this.y - pos.y)
}

RoomPosition.prototype.serialize = function () {
  return Room.serializeName(this.roomName) + String.fromCharCode(((this.x * 100) + +this.y) + 200)
}

RoomPosition.deserialize = function (string) {
  const roomname = Room.deserializeName(string.slice(0, -1))
  const coordraw = (string.charCodeAt(string.length - 1) - 200)
  const x = Math.floor(coordraw / 100)
  const y = coordraw % 50
  return new RoomPosition(x, y, roomname)
}

RoomPosition.prototype.lookAroundFor = function (type, range = 1) {
  if (!Game.rooms[this.roomName]) {
    return ERR_INVALID_TARGET
  }
  const room = Game.rooms[this.roomName]
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  return room.lookForAtArea(type, bounds.top, bounds.left, bounds.bottom, bounds.right, true)
}

RoomPosition.prototype.lookAround = function (range = 1) {
  if (!Game.rooms[this.roomName]) {
    return ERR_INVALID_TARGET
  }
  const room = Game.rooms[this.roomName]
  const bounds = createBoundingBoxForRange(this.x, this.y, range)
  return room.lookAtArea(bounds.top, bounds.left, bounds.bottom, bounds.right, true)
}

/**
 * Creates a bounding box clamped inside the borders of the room
 * @param {number} x position to get bounds-range from
 * @param {number} y position to get bounds-range from
 * @param {number} range of the bounding box
 * @returns {{left: number, right: number, top: number, bottom: number}}
 */
function createBoundingBoxForRange (x, y, range) {
  const absRange = Math.abs(range)
  const left = Math.min(Math.max(x - absRange, 0), 49)
  const right = Math.max(Math.min(x + absRange, 49), 0)
  const top = Math.min(Math.max(y - absRange, 0), 49)
  const bottom = Math.max(Math.min(y + absRange, 49), 0)
  return {left, right, top, bottom}
}

module.exports = {
  createBoundingBoxForRange
}
<|endoftext|>


<commit_before>/*
 * Copyright 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * Please see distribution for license.
 *
 * autosuggest combobox
 *
 */
$.register_module({
    name: 'og.common.util.ui.AutoCombo',
    dependencies: [],
    obj: function () {
        /**
         * @param {Object} obj configuration object,
         * selector (String) and data (Array) are required, placeholder (String) is optional
         */
        return function (selector, placeholder, data) {
            var $wrapper, $input, $button,
                list = data.map(function (val) {return val.replace(/^.*\|(.*)\|.*$/, '$1');}), autocomplete_obj,
                open = function () {
                    $wrapper.blurkill(function () {$input.autocomplete('close');});
                    // open using the current input value or an empty string
                    $input.autocomplete('search', ($input.val() !== placeholder) ? ($input.val() || '') : '').select();
                };
            placeholder = placeholder || '';
            autocomplete_obj = {
                minLength: 0, delay: 0,
                source: function (req, res) {
                    var escaped = $.ui.autocomplete.escapeRegex(req.term),
                        matcher = new RegExp(escaped, 'i'),
                        htmlize = function (str) {
                            return !req.term ? str : str.replace(
                                new RegExp('(?![^&;]+;)(?!<[^<>]*)(' + escaped + ')(?![^<>]*>)(?![^&;]+;)', 'gi'),
                                '$1'
                            );
                        };
                    res(list.reduce(function (acc, val) {
                        if (val && (!req.term || matcher.test(val))) acc.push({label: htmlize(val), value: val});
                        return acc;
                    }, []));
                }
            };
            $wrapper = $('
'); // wrap input in div to enable input width at 100% of parent, FF, IE
            $input = $wrapper.html('<input type="text" />').find('input')
                .autocomplete(autocomplete_obj).attr('placeholder', placeholder).on('mouseup', open)
                .on('blur', function () {if ($input.val() === placeholder) $input.val('');})
                .on('focus', function () {$input.trigger('open', $input)});
            // Enable html list items
            $input.data('autocomplete')._renderItem = function(ul, item) {
                return $('

').data('item.autocomplete', item).append('' + item.label + '').appendTo(ul);
            };
            $button = $('

').on('click', function () {
                return $input.autocomplete('widget').is(':visible') ? $input.autocomplete('close').select() : open();
            });
            $([$wrapper, $button]).prependTo(selector);
            return $input;
        }
    }
});<commit_msg>blurkill was preventing default autosuggest behaviour<commit_after>/*
 * Copyright 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * Please see distribution for license.
 *
 * autosuggest combobox
 *
 */
$.register_module({
    name: 'og.common.util.ui.AutoCombo',
    dependencies: [],
    obj: function () {
        /**
         * @param {Object} obj configuration object,
         * selector (String) and data (Array) are required, placeholder (String) is optional
         */
        return function (selector, placeholder, data) {
            var $wrapper, $input, $button,
                list = data.map(function (val) {return val.replace(/^.*\|(.*)\|.*$/, '$1');}), autocomplete_obj,
                open = function () {
                    // open using the current input value or an empty string
                    $input.autocomplete('search', ($input.val() !== placeholder) ? ($input.val() || '') : '').select();
                };
            placeholder = placeholder || '';
            autocomplete_obj = {
                minLength: 0, delay: 0,
                open: function() {$(this).autocomplete('widget').blurkill(function () {$input.autocomplete('close')});},
                source: function (req, res) {
                    var escaped = $.ui.autocomplete.escapeRegex(req.term),
                        matcher = new RegExp(escaped, 'i'),
                        htmlize = function (str) {
                            return !req.term ? str : str.replace(
                                new RegExp('(?![^&;]+;)(?!<[^<>]*)(' + escaped + ')(?![^<>]*>)(?![^&;]+;)', 'gi'),
                                '$1'
                            );
                        };
                    res(list.reduce(function (acc, val) {
                        if (val && (!req.term || matcher.test(val))) acc.push({label: htmlize(val), value: val});
                        return acc;
                    }, []));
                }
            };
            $wrapper = $('
'); // wrap input in div to enable input width at 100% of parent, FF, IE
            $input = $wrapper.html('<input type="text" />').find('input')
                .autocomplete(autocomplete_obj).attr('placeholder', placeholder).on('mouseup', open)
                .on('blur', function () {if ($input.val() === placeholder) $input.val('');})
                .on('focus', function () {$input.trigger('open', $input)});
            // Enable html list items
            $input.data('autocomplete')._renderItem = function(ul, item) {
                return $('

').data('item.autocomplete', item).append('' + item.label + '').appendTo(ul);
            };
            $button = $('

').on('click', function () {
                return $input.autocomplete('widget').is(':visible') ? $input.autocomplete('close').select() : open();
            });
            $([$wrapper, $button]).prependTo(selector);
            return $input;
        }
    }
});<|endoftext|>


<commit_before>/* ***********************************************************************************************

    Unify Project

    Homepage: unify-project.org
    License: MIT + Apache (V2)
    Copyright: 2009-2010 Deutsche Telekom AG, Germany, http://telekom.com

*********************************************************************************************** */

/**
 * The TitleBar may be used as the first control of the {@link Layer}
 * for showing a title and offering simple navigation options. As the {@link ToolBar}
 * it might show additional buttons on the right side for navigation proposes.
 */
qx.Class.define("unify.ui.NavigationBar",
{
  extend : unify.ui.Abstract,

  /*
  *****************************************************************************
     CONSTRUCTOR
  *****************************************************************************
  */

  /**
   * @param view {unify.view.Static} View controller to connect to
   */
  construct : function(view)
  {
    this.base(arguments);

    if (!view || !(view instanceof unify.view.StaticView)) {
      throw new Error("Invalid view! NavigationBar must be attached to a view!")
    }

    this.__view = view;

    // Finally listen for any changes occour after creation of the titlebar
    view.addListener("changeTitle", this.__onViewChangeTitle, this);
    view.addListener("changeParent", this.__onViewChangeParent, this);
    view.addListener("changeMaster", this.__onViewChangeMaster, this);

    this.__onViewChangeParent();
    this.__onViewChangeMaster();
  },

  /*
  *****************************************************************************
     MEMBERS
  *****************************************************************************
  */

  members :
  {
    _createElement : function()
    {
      var elem = document.createElement("div");
      elem.className = "navigation-bar";
      elem.innerHTML = this.__view.getTitle();

      return elem;
    },

    /*
    ---------------------------------------------------------------------------
      EVENT LISTENER
    ---------------------------------------------------------------------------
    */

    __lastParentTitle : null,
    __lastMasterTitle : null,

    /**
     * Event listener for parent changes
     *
     * @param e {qx.event.type.Data} Data event
     */
    __onViewChangeParent : function(e)
    {
      return;

      var parentView = this.__view.getParent();
      var parentButtonElem = this.query("[rel=parent]");

      if (parentView)
      {
        var parentTitle = parentView.getTitle("parent");

        if (this.__lastParentTitle != parentTitle)
        {
          if (parentButtonElem)
          {
            parentButtonElem.innerHTML = parentTitle;
            parentButtonElem.style.display = "";
          }
          else
          {
            this.add(
            {
              label : parentTitle,
              rel : "parent"
            });
          }

          this.__lastParentTitle = parentTitle;
        }
      }
      else
      {
        if (parentButtonElem) {
          parentButtonElem.style.display = "none";
        }

        this.__lastParentTitle = null;
      }
    },

    /**
     * Event listener for master changes
     *
     * @param e {qx.event.type.Data} Data event
     */
    __onViewChangeMaster : function(e)
    {
      return;

      var masterViewManager = this.getView().getMaster();
      var masterButtonElem = this.query("[rel=master]");

      if (masterViewManager)
      {
        var masterView = masterViewManager.getCurrentView();
        var masterTitle = masterView.getTitle("master");

        if (this.__lastMasterTitle != masterTitle)
        {
          if (masterButtonElem)
          {
            masterButtonElem.innerHTML = masterTitle;
            masterButtonElem.style.display = "";
          }
          else
          {
            this.add(
            {
              label : masterTitle,
              rel : "master"
            });
          }

          this.__lastMasterTitle = masterTitle;
        }
      }
      else
      {
        if (masterButtonElem) {
          masterButtonElem.style.display = "none";
        }

        this.__lastMasterTitle = null;
      }
    },

    /**
     * Event listner for changeTitle event of attached view.
     *
     * @param e {qx.event.type.Data} Property change event
     */
    __onViewChangeTitle : function(e)
    {
      return;

      this.query(".center").innerHTML = this.getView().getTitle("titlebar");
    }
  },

  /*
  *****************************************************************************
     DESTRUCTOR
  *****************************************************************************
  */

  destruct : function()
  {
    var view = this.__view
    view.removeListener("changeTitle", this.__onViewChangeTitle, this);
    view.removeListener("changeParent", this.__onViewChangeParent, this);
  }
});
<commit_msg>Worked on NavigationBar<commit_after>/* ***********************************************************************************************

    Unify Project

    Homepage: unify-project.org
    License: MIT + Apache (V2)
    Copyright: 2009-2010 Deutsche Telekom AG, Germany, http://telekom.com

*********************************************************************************************** */

/**
 * The TitleBar may be used as the first control of the {@link Layer}
 * for showing a title and offering simple navigation options. As the {@link ToolBar}
 * it might show additional buttons on the right side for navigation proposes.
 */
qx.Class.define("unify.ui.NavigationBar",
{
  extend : unify.ui.Abstract,

  /*
  *****************************************************************************
     CONSTRUCTOR
  *****************************************************************************
  */

  /**
   * @param view {unify.view.Static} View controller to connect to
   */
  construct : function(view)
  {
    this.base(arguments);

    if (!view || !(view instanceof unify.view.StaticView)) {
      throw new Error("Invalid view! NavigationBar must be attached to a view!")
    }

    this.__view = view;

    // Finally listen for any changes occour after creation of the titlebar
    view.addListener("changeTitle", this.__onViewChangeTitle, this);
    view.addListener("changeParent", this.__onViewChangeParent, this);
    view.addListener("changeMaster", this.__onViewChangeMaster, this);

    this.__onViewChangeParent();
    this.__onViewChangeMaster();
  },

  /*
  *****************************************************************************
     MEMBERS
  *****************************************************************************
  */

  properties :
  {
    leftItem :
    {
      nullable : true
    },

    rightItem :
    {
      nullable : true
    }
  },

  members :
  {
    _createElement : function()
    {
      var elem = document.createElement("div");
      elem.className = "navigation-bar";

      var titleElem = this.__titleElem = document.createElement("h1");
      titleElem.innerHTML = this.__view.getTitle();
      elem.appendChild(titleElem);

      var leftElem = this.__leftElem = document.createElement("div");
      leftElem.className = "left";
      elem.appendChild(leftElem);

      var rightElem = this.__rightElem = document.createElement("div");
      rightElem.className = "right";
      elem.appendChild(rightElem);

      return elem;
    },

    /*
    ---------------------------------------------------------------------------
      EVENT LISTENER
    ---------------------------------------------------------------------------
    */

    __lastParentTitle : null,
    __lastMasterTitle : null,

    /**
     * Event listener for parent changes
     *
     * @param e {qx.event.type.Data} Data event
     */
    __onViewChangeParent : function(e)
    {
      return;

      var parentView = this.__view.getParent();
      var parentButtonElem = this.query("[rel=parent]");

      if (parentView)
      {
        var parentTitle = parentView.getTitle("parent");

        if (this.__lastParentTitle != parentTitle)
        {
          if (parentButtonElem)
          {
            parentButtonElem.innerHTML = parentTitle;
            parentButtonElem.style.display = "";
          }
          else
          {
            this.add(
            {
              label : parentTitle,
              rel : "parent"
            });
          }

          this.__lastParentTitle = parentTitle;
        }
      }
      else
      {
        if (parentButtonElem) {
          parentButtonElem.style.display = "none";
        }

        this.__lastParentTitle = null;
      }
    },

    /**
     * Event listener for master changes
     *
     * @param e {qx.event.type.Data} Data event
     */
    __onViewChangeMaster : function(e)
    {
      return;

      var masterViewManager = this.getView().getMaster();
      var masterButtonElem = this.query("[rel=master]");

      if (masterViewManager)
      {
        var masterView = masterViewManager.getCurrentView();
        var masterTitle = masterView.getTitle("master");

        if (this.__lastMasterTitle != masterTitle)
        {
          if (masterButtonElem)
          {
            masterButtonElem.innerHTML = masterTitle;
            masterButtonElem.style.display = "";
          }
          else
          {
            this.add(
            {
              label : masterTitle,
              rel : "master"
            });
          }

          this.__lastMasterTitle = masterTitle;
        }
      }
      else
      {
        if (masterButtonElem) {
          masterButtonElem.style.display = "none";
        }

        this.__lastMasterTitle = null;
      }
    },

    /**
     * Event listner for changeTitle event of attached view.
     *
     * @param e {qx.event.type.Data} Property change event
     */
    __onViewChangeTitle : function(e)
    {
      return;

      this.query(".center").innerHTML = this.getView().getTitle("titlebar");
    }
  },

  /*
  *****************************************************************************
     DESTRUCTOR
  *****************************************************************************
  */

  destruct : function()
  {
    var view = this.__view
    view.removeListener("changeTitle", this.__onViewChangeTitle, this);
    view.removeListener("changeParent", this.__onViewChangeParent, this);
  }
});
<|endoftext|>


<commit_before>/**
 * New node file
 */
var Offer		 = require('../app/models/offer');
var OfferHistory = require('../app/models/offerHistory');
var Comment		 = require('../app/models/comment');
var Product 	 = require('../app/models/product');

//for test
exports.testSaveOffer = function(req, res){

	var newOffer=new Offer();
	newOffer.offerId="1";
	newOffer.buyingQty=100;

	newOffer.save(function(err){
		if(err){
			res.status(500).json({status:'failure'});
			console.log("failure to save");
		}
		else{
			res.send('saveResult', {
				status: "success"
			});
		}
	});

};

//for test
exports.testGetAllOffer = function(req, res){
	Offer.find()
	.exec(function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else{
			res.send('allOfferDetails', {
				allOfferDetails: result
			});
		}
	});

};

//GET
//Yuan
//'/category/:categoryId/product/'
/*
exports.getAllProduct = function(req, res){
	Product.find({}, function(err, products){
		if(err) {
			res.status(500).json({status:'failure'});
			console.log("Get all product error!");
		} else if(products===null) {
			res.send("could not find any product");
			console.log("could not find any product");
		} else {
			var productlist = [];

			products.forEach(function(product) {
				console.log(product);
				productlist.push(product);
			});

			res.status(200).json(productlist);
		}
	});
};
*/

//GET
//Yuan
//with category Id
//'/category/:categoryId/product/'
exports.getAllProduct = function(req, res){
	var categoryId = req.param('categoryId');

	Product.find({'categoryId': categoryId}, function(err, products){
		if(err) {
			res.status(500).json({status:'failure'});
			console.log("Get all product error!" + " category Id: " + categoryId);
		} else if(products === null) {
			res.send("could not find any product from category Id: " + categoryId);
			console.log("could not find any product from category Id: " + categoryId);
		} else {
			var productlist = [];

			products.forEach(function(product) {
				console.log(product);
				productlist.push(product);
			});

			res.status(200).json(productlist);
		}
	});
};

//Post
//Yuan
//'/category/:categoryId/product/'
exports.addProduct = function(req, res){
	var newProduct = new Product();
	Product.count({ productId:{$exists: true} },
			function (err, count){
				newProduct.productId 		 = count + 1;
				newProduct.productName 		 = req.param('productName');
				newProduct.quantity 		 = req.param('quantity');
				newProduct.userId 			 = req.param('userId');
				newProduct.expectedOffer 	 = req.param('productName');
				newProduct.productExpiryDate = req.param('productExpiryDate');
				newProduct.isValid 			 = req.param('isValid');
				newProduct.categoryId 		 = req.param('categoryId');
				newProduct.lastUpdated 		 = req.param('lastUpdated');

				newProduct.save(function(err){
					if(err){
						res.status(500).json({status:'failure'});
						console.log("failure to save new product");
					}
					else{
						res.status(200).json({
							productId 			: newProduct.productId,
							productName 		: newProduct.productName,
							quantity 			: newProduct.quantity,
							userId 				: newProduct.userId,
							expectedOffer 		: newProduct.expectedOffer,
							productDesc 		: newProduct.productDesc,
							productExpiryDate 	: newProduct.productExpiryDate,
							isValid 			: newProduct.isValid,
							categoryId 			: newProduct.categoryId,
							lastUpdated 		: newProduct.lastUpdated
						});
					}
			});

	});

};

//GET
//Yuan
//'/category/:categoryId/product/:productId'

//PUT
//Yuan
//'/category/:categoryId/product/:productId'

//DELETE
//Yuan
//'/category/:categoryId/product/:productId'

//GET
//'/category/:categoryId/product/:productId/offer/:offerId'
exports.getOfferDetail = function(req, res){
	var offerId = req.param('offerId');

	Offer.findOne({"offerId": offerId}, function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(result===null){
			res.send("could not find offer with this offerId");
		}
		else{
			var offer=result;

			//find last event of found offer
			//TODO need to optimize the search parameter to find last history
			OfferHistory.findOne({"offerId": offerId,
								"lastModified": offer.lastModified
								},
							function(err,foundHistory){
				var foundLastEvent=null;

				if(foundHistory===null){
					console.log("no update history found for this offer");
				}
				else{
					foundLastEvent =foundHistory.modified;
				}
				//find all the comments of this offer
				Comment.find({"offerId": offerId}, function(err,foundComments){
					//show offer details
					res.status(200).json({
						offerId : offer.offerId,
						buyingQty : offer.buyingQty,
						offeredDetails : offer.offeredDetails,
						buyerStatus : offer.buyerStatus,
						sellerStatus : offer.sellerStatus,
						offerExpiry : offer.offerExpiry,
						productId : offer.productId,
						buyerId : offer.buyerId,
						lastModified : offer.lastModified,
						//add last Event here
						lastEvent : foundLastEvent,
						// add comments here
						comments : foundComments
					});

				});
			});

		}
	});

};

//PUT
//'/category/:categoryId/product/:productId/offer/:offerId'
exports.updateOffer = function(req, res){
	var offerId = req.param('offerId');
	Offer.findOne({"offerId": offerId}, function(err,offer){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(offer===null){
			res.send("could not find offer with this offerId");
		}
		else{
			//update found offer
			offer.offerId=req.param('offerId');
			offer.buyingQty=req.param('buyingQty');
			offer.offeredDetails=req.param('offeredDetails');
			offer.buyerStatus=req.param('buyerStatus');
			offer.sellerStatus=req.param('sellerStatus');
			offer.offerExpiry=req.param('offerExpiry');
			offer.productId=req.param('productId');
			offer.buyerId=req.param('buyerId');
			offer.lastModified=new Date();
			offer.save(function(err){
				if(err){
					res.status(500).json({status:'failure'});
					console.log("failure to update found offer");
				}
				else{
					//insert a record in OfferHistory
					var newHistory= new OfferHistory();
					OfferHistory.count({ offerHistoryId:{$exists: true} },
							function (err, count){
								newHistory.offerHistoryId = count+1;
								newHistory.offerId = offer.offerId;
								//TODO need to decide what should be stored
								// for newHistory.modified
								newHistory.modified = offer;
								//newHistory.lastModified = new Date();
								// or store the time that offer is updated
								newHistory.lastModified = offer.lastModified;
								newHistory.save(function(err){
									 if(err){
										 console.log("failure to save history");
									 }
								});
							}
					);

					//find all the comments of this offer
					Comment.find({"offerId": offerId}, function(err,foundComments){
						//show update result
						res.status(200).json({
							offerId : offer.offerId,
							buyingQty : offer.buyingQty,
							offeredDetails : offer.offeredDetails,
							buyerStatus : offer.buyerStatus,
							sellerStatus : offer.sellerStatus,
							offerExpiry : offer.offerExpiry,
							productId : offer.productId,
							buyerId : offer.buyerId,
							lastModified : offer.lastModified,
							// add comments here
							comments : foundComments
						});

					});
				}
			});

		}

	});

};

//DELETE
//'/category/:categoryId/product/:productId/offer/:offerId'
exports.deleteOffer = function(req, res){
	var offerId = req.param('offerId');
	Offer.remove({ "offerId": offerId }, function(err) {
	    if (!err) {
	    	var removeOffer=true;
	    	var removeHistory=true;
	    	var removeComment=true;
	    	OfferHistory.remove({ "offerId": offerId }, function(err) {
	    			if(err){
	    				removeHistory=false;
	    			}
	    			Comment.remove({ "offerId": offerId }, function(err) {
	    				if(err){
	    					removeComment=false;
	    				}
	    			});
	    	});

	    	res.status(200)
	    		.json({
	    		status:'success',
		    	removeOffer : removeOffer,
	    		removeHistory : removeHistory,
	    		removeComment: removeComment
	    		});
	    }
	    else {
	    	res.status(500).json({status:'delete offer failure'});
	    }
	});

};

//POST
//'/category/:categoryId/product/:productId/offer/:offerId/comment'
exports.addOfferComment = function(req, res){
	var newComment= new Comment();
	Comment.count({ commentId:{$exists: true} },
			function (err, count){
				newComment.commentId = count+1;
				newComment.offerId = req.param('offerId');
				newComment.userId = req.param('userId');
				newComment.commentDesc = req.param('commentDesc');
				newComment.lastUpdated = new Date();

				newComment.save(function(err){
					if(err){
						res.status(500).json({status:'failure'});
						console.log("failure to save");
					}
					else{
						res.status(200).json({
							_id : newComment._id,
							commentId :newComment.commentId,
							comment : newComment.commentDesc,
							userId : newComment.userId

						});
					}
			});

	});

};

//for test
//GET
//'/category/:categoryId/product/:productId/offer/:offerId/comment'
exports.getOfferComment = function(req, res){
	var offerId = req.param('offerId');
	Comment.find({"offerId": offerId}, function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(result===null){
			res.send("could not find comment with this offerId");
		}
		else{
			res.status(200).json({
				comments: result
			});
		}
	});

};

//for test
//POST
//'/category/:categoryId/product/:productId/offer/:offerId/history'
exports.addOfferHistory = function(req, res){
	var newHistory= new OfferHistory();
	OfferHistory.count({ offerHistoryId:{$exists: true} },
			function (err, count){
				newHistory.offerHistoryId = count+1;
				newHistory.offerId = req.param('offerId');
				newHistory.modified = req.param('modified');
				newHistory.lastModified  = new Date();

				newHistory.save(function(err){
					if(err){
						res.status(500).json({status:'failure'});
						console.log("failure to save");
					}
					else{
						res.status(200).json({
							_id : newHistory._id,
							offerHistoryId :newHistory.offerHistoryId,
							offerId : newHistory.offerId,
							modified : newHistory.modified,
							lastModified : newHistory.lastModified

						});
					}
			});

	});

};

//GET
//'/category/:categoryId/product/:productId/offer/:offerId/history'
exports.getOfferHistory = function(req, res){
	var offerId = req.param('offerId');
	OfferHistory.find({"offerId": offerId}, function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(result===null){
			res.send("could not find comment with this offerId");
		}
		else{
			res.status(200).json({
				offerHistory: result
			});
		}
	});

};

<commit_msg>update post product routing<commit_after>/**
 * New node file
 */
var Offer		 = require('../app/models/offer');
var OfferHistory = require('../app/models/offerHistory');
var Comment		 = require('../app/models/comment');
var Product 	 = require('../app/models/product');

//for test
exports.testSaveOffer = function(req, res){

	var newOffer=new Offer();
	newOffer.offerId="1";
	newOffer.buyingQty=100;

	newOffer.save(function(err){
		if(err){
			res.status(500).json({status:'failure'});
			console.log("failure to save");
		}
		else{
			res.send('saveResult', {
				status: "success"
			});
		}
	});

};

//for test
exports.testGetAllOffer = function(req, res){
	Offer.find()
	.exec(function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else{
			res.send('allOfferDetails', {
				allOfferDetails: result
			});
		}
	});

};

//GET
//Yuan
//'/category/:categoryId/product/'
/*
exports.getAllProduct = function(req, res){
	Product.find({}, function(err, products){
		if(err) {
			res.status(500).json({status:'failure'});
			console.log("Get all product error!");
		} else if(products===null) {
			res.send("could not find any product");
			console.log("could not find any product");
		} else {
			var productlist = [];

			products.forEach(function(product) {
				console.log(product);
				productlist.push(product);
			});

			res.status(200).json(productlist);
		}
	});
};
*/

//GET
//Yuan
//with category Id
//'/category/:categoryId/product/'
exports.getAllProduct = function(req, res){
	var categoryId = req.param('categoryId');

	Product.find({'categoryId': categoryId}, function(err, products){
		if(err) {
			res.status(500).json({status:'failure'});
			console.log("Get all product error!" + " category Id: " + categoryId);
		} else if(products === null) {
			res.send("could not find any product from category Id: " + categoryId);
			console.log("could not find any product from category Id: " + categoryId);
		} else {
			var productlist = [];

			products.forEach(function(product) {
				console.log(product);
				productlist.push(product);
			});

			res.status(200).json(productlist);
		}
	});
};

//Post
//Yuan
//'/category/:categoryId/product/'
exports.addProduct = function(req, res){
	var newProduct = new Product();
	Product.count({ productId:{$exists: true} },
			function (err, count){
				newProduct.productId 		 = count + 1;
				newProduct.productName 		 = req.param('productName');
				newProduct.quantity 		 = req.param('quantity');
				newProduct.userId 			 = req.param('userId');
				newProduct.expectedOffer 	 = req.param('expectedOffer');
				newProduct.productExpiryDate = req.param('productExpiryDate');
				newProduct.isValid 			 = req.param('isValid');
				newProduct.categoryId 		 = req.param('categoryId');
				newProduct.lastUpdated 		 = req.param('lastUpdated');

				newProduct.save(function(err){
					if(err){
						res.status(500).json({status:'failure'});
						console.log("failure to save new product");
					}
					else{
						res.status(200).json({
							productId 			: newProduct.productId,
							productName 		: newProduct.productName,
							quantity 			: newProduct.quantity,
							userId 				: newProduct.userId,
							expectedOffer 		: newProduct.expectedOffer,
							productDesc 		: newProduct.productDesc,
							productExpiryDate 	: newProduct.productExpiryDate,
							isValid 			: newProduct.isValid,
							categoryId 			: newProduct.categoryId,
							lastUpdated 		: newProduct.lastUpdated
						});
					}
			});

	});

};

//GET
//Yuan
//'/category/:categoryId/product/:productId'

//PUT
//Yuan
//'/category/:categoryId/product/:productId'

//DELETE
//Yuan
//'/category/:categoryId/product/:productId'

//GET
//'/category/:categoryId/product/:productId/offer/:offerId'
exports.getOfferDetail = function(req, res){
	var offerId = req.param('offerId');

	Offer.findOne({"offerId": offerId}, function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(result===null){
			res.send("could not find offer with this offerId");
		}
		else{
			var offer=result;

			//find last event of found offer
			//TODO need to optimize the search parameter to find last history
			OfferHistory.findOne({"offerId": offerId,
								"lastModified": offer.lastModified
								},
							function(err,foundHistory){
				var foundLastEvent=null;

				if(foundHistory===null){
					console.log("no update history found for this offer");
				}
				else{
					foundLastEvent =foundHistory.modified;
				}
				//find all the comments of this offer
				Comment.find({"offerId": offerId}, function(err,foundComments){
					//show offer details
					res.status(200).json({
						offerId : offer.offerId,
						buyingQty : offer.buyingQty,
						offeredDetails : offer.offeredDetails,
						buyerStatus : offer.buyerStatus,
						sellerStatus : offer.sellerStatus,
						offerExpiry : offer.offerExpiry,
						productId : offer.productId,
						buyerId : offer.buyerId,
						lastModified : offer.lastModified,
						//add last Event here
						lastEvent : foundLastEvent,
						// add comments here
						comments : foundComments
					});

				});
			});

		}
	});

};

//PUT
//'/category/:categoryId/product/:productId/offer/:offerId'
exports.updateOffer = function(req, res){
	var offerId = req.param('offerId');
	Offer.findOne({"offerId": offerId}, function(err,offer){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(offer===null){
			res.send("could not find offer with this offerId");
		}
		else{
			//update found offer
			offer.offerId=req.param('offerId');
			offer.buyingQty=req.param('buyingQty');
			offer.offeredDetails=req.param('offeredDetails');
			offer.buyerStatus=req.param('buyerStatus');
			offer.sellerStatus=req.param('sellerStatus');
			offer.offerExpiry=req.param('offerExpiry');
			offer.productId=req.param('productId');
			offer.buyerId=req.param('buyerId');
			offer.lastModified=new Date();
			offer.save(function(err){
				if(err){
					res.status(500).json({status:'failure'});
					console.log("failure to update found offer");
				}
				else{
					//insert a record in OfferHistory
					var newHistory= new OfferHistory();
					OfferHistory.count({ offerHistoryId:{$exists: true} },
							function (err, count){
								newHistory.offerHistoryId = count+1;
								newHistory.offerId = offer.offerId;
								//TODO need to decide what should be stored
								// for newHistory.modified
								newHistory.modified = offer;
								//newHistory.lastModified = new Date();
								// or store the time that offer is updated
								newHistory.lastModified = offer.lastModified;
								newHistory.save(function(err){
									 if(err){
										 console.log("failure to save history");
									 }
								});
							}
					);

					//find all the comments of this offer
					Comment.find({"offerId": offerId}, function(err,foundComments){
						//show update result
						res.status(200).json({
							offerId : offer.offerId,
							buyingQty : offer.buyingQty,
							offeredDetails : offer.offeredDetails,
							buyerStatus : offer.buyerStatus,
							sellerStatus : offer.sellerStatus,
							offerExpiry : offer.offerExpiry,
							productId : offer.productId,
							buyerId : offer.buyerId,
							lastModified : offer.lastModified,
							// add comments here
							comments : foundComments
						});

					});
				}
			});

		}

	});

};

//DELETE
//'/category/:categoryId/product/:productId/offer/:offerId'
exports.deleteOffer = function(req, res){
	var offerId = req.param('offerId');
	Offer.remove({ "offerId": offerId }, function(err) {
	    if (!err) {
	    	var removeOffer=true;
	    	var removeHistory=true;
	    	var removeComment=true;
	    	OfferHistory.remove({ "offerId": offerId }, function(err) {
	    			if(err){
	    				removeHistory=false;
	    			}
	    			Comment.remove({ "offerId": offerId }, function(err) {
	    				if(err){
	    					removeComment=false;
	    				}
	    			});
	    	});

	    	res.status(200)
	    		.json({
	    		status:'success',
		    	removeOffer : removeOffer,
	    		removeHistory : removeHistory,
	    		removeComment: removeComment
	    		});
	    }
	    else {
	    	res.status(500).json({status:'delete offer failure'});
	    }
	});

};

//POST
//'/category/:categoryId/product/:productId/offer/:offerId/comment'
exports.addOfferComment = function(req, res){
	var newComment= new Comment();
	Comment.count({ commentId:{$exists: true} },
			function (err, count){
				newComment.commentId = count+1;
				newComment.offerId = req.param('offerId');
				newComment.userId = req.param('userId');
				newComment.commentDesc = req.param('commentDesc');
				newComment.lastUpdated = new Date();

				newComment.save(function(err){
					if(err){
						res.status(500).json({status:'failure'});
						console.log("failure to save");
					}
					else{
						res.status(200).json({
							_id : newComment._id,
							commentId :newComment.commentId,
							comment : newComment.commentDesc,
							userId : newComment.userId

						});
					}
			});

	});

};

//for test
//GET
//'/category/:categoryId/product/:productId/offer/:offerId/comment'
exports.getOfferComment = function(req, res){
	var offerId = req.param('offerId');
	Comment.find({"offerId": offerId}, function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(result===null){
			res.send("could not find comment with this offerId");
		}
		else{
			res.status(200).json({
				comments: result
			});
		}
	});

};

//for test
//POST
//'/category/:categoryId/product/:productId/offer/:offerId/history'
exports.addOfferHistory = function(req, res){
	var newHistory= new OfferHistory();
	OfferHistory.count({ offerHistoryId:{$exists: true} },
			function (err, count){
				newHistory.offerHistoryId = count+1;
				newHistory.offerId = req.param('offerId');
				newHistory.modified = req.param('modified');
				newHistory.lastModified  = new Date();

				newHistory.save(function(err){
					if(err){
						res.status(500).json({status:'failure'});
						console.log("failure to save");
					}
					else{
						res.status(200).json({
							_id : newHistory._id,
							offerHistoryId :newHistory.offerHistoryId,
							offerId : newHistory.offerId,
							modified : newHistory.modified,
							lastModified : newHistory.lastModified

						});
					}
			});

	});

};

//GET
//'/category/:categoryId/product/:productId/offer/:offerId/history'
exports.getOfferHistory = function(req, res){
	var offerId = req.param('offerId');
	OfferHistory.find({"offerId": offerId}, function(err,result){
		if(err){
			res.status(500).json({status:'failure'});
		}
		else if(result===null){
			res.send("could not find comment with this offerId");
		}
		else{
			res.status(200).json({
				offerHistory: result
			});
		}
	});

};

<|endoftext|>


<commit_before>import fsp from 'fs-promise';
import lodash from 'lodash';

export function getCommitMsg (path) {
  return fsp.readFile(path, {encoding: 'utf8'});
}

export function getIssueReference(msgToParse, prjKey) {
  let pattern = RegExp(`${prjKey}-\\d+`, 'g');
  let commentPattern = RegExp(`^#.*$`, 'gm');

  msgToParse = msgToParse.replace(commentPattern, '');
  let references = msgToParse.match(pattern);

  return lodash.unique(references);
}
<commit_msg>Rename lodash variable to _<commit_after>import fsp from 'fs-promise';
import _ from 'lodash';

export function getCommitMsg (path) {
  return fsp.readFile(path, {encoding: 'utf8'});
}

export function getIssueReference(msgToParse, prjKey) {
  let pattern = RegExp(`${prjKey}-\\d+`, 'g');
  let commentPattern = RegExp(`^#.*$`, 'gm');

  msgToParse = msgToParse.replace(commentPattern, '');
  let references = msgToParse.match(pattern);

  return _.unique(references);
}
<|endoftext|>