<commit_before>/* globals helper */
describe('toast.drminfo', function() {
    it('should be defined as "toast.drminfo" namespace.', function() {
        expect(window.toast).toBeDefined();
        expect(window.toast.drminfo).toBeDefined();
    });
    it('should contain a "getVersion" function.', function() {
        expect(window.toast.drminfo.getVersion).toBeDefined();
        expect(typeof window.toast.drminfo.getVersion).toBe('function');
    });
    it('should contain a "getEsn" function.', function() {
        expect(window.toast.drminfo.getEsn).toBeDefined();
        expect(typeof window.toast.drminfo.getEsn).toBe('function');
    });
    it('should contain a "getSdiId" function.', function() {
        expect(window.toast.drminfo.getSdiId).toBeDefined();
        expect(typeof window.toast.drminfo.getSdiId).toBe('function');
    });
    it('should not contain a property that is not exists in the specs.', function() {
        for (var prop in toast.drminfo) {
            expect([
                'getVersion',
                'getEsn',
                'getSdiId'
            ].indexOf(prop) >= 0).toBeTruthy();
        }
    });
    describe('toast.drminfo.getVersion', function() {
        it('returns plugin version as string', function (done) {
            var version = null;
            toast.drminfo.getVersion(function(value){
                version = value;
                expect(version).toBeDefined();
                expect(typeof version).toBe('string');
                done();
            }, function(){
                done.fail();
            });
        }, 3000);
        it('throws TypeError when given arguments is not matched to spec.', function() {
            // no argument
            expect(function() {
                toast.drminfo.getVersion();
            }).toThrowError(TypeError);

            // invalid type for 1st argument
            expect(function() {
                toast.drminfo.getVersion([]);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion({});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(false);
            }).toThrowError(TypeError);

            // invalid type for 2nd argument
            expect(function() {
                toast.drminfo.getVersion(function(){}, []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(function(){}, new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(function(){}, 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(function(){}, {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getVersion(function(){}, false);
            }).toThrowError(TypeError);
        });
    });
    describe('toast.drminfo.getEsn', function() {
        it('returns Esn value as string', function (done) {
            var esn = null;
            toast.drminfo.getEsn('WIDEVINE', function(value){
                esn = value;
                expect(esn).toBeDefined();
                expect(typeof esn).toBe('string');
                done();
            }, function(){
                done.fail();
            });
        }, 3000);
        it('throws TypeError when given arguments is not matched to spec.', function() {
            // no argument
            expect(function() {
                toast.drminfo.getEsn();
            }).toThrowError(TypeError);

            // invalid type for 1st argument
            expect(function() {
                toast.drminfo.getEsn([]);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(function () {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn({});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(false);
            }).toThrowError(TypeError);

            // invalid type for 2nd argument
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', false);
            }).toThrowError(TypeError);

            // invalid type for 3rd argument
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, false);
            }).toThrowError(TypeError);
        });
    });
    describe('toast.drminfo.getSdiId', function() {
        it('returns SDI(Samsung Device Identifier) as string', function (done) {
            var sdi = null;
            toast.drminfo.getSdiId(function(value){
                sdi = value;
                expect(sdi).toBeDefined();
                expect(typeof sdi).toBe('string');
                done();
            }, function(){
                done.fail();
            });
        }, 3000);
        it('throws TypeError when given arguments is not matched to spec.', function() {
            // no argument
            expect(function() {
                toast.drminfo.getSdiId();
            }).toThrowError(TypeError);

            // invalid type for 1st argument
            expect(function() {
                toast.drminfo.getSdiId([]);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId({});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(false);
            }).toThrowError(TypeError);

            // invalid type for 2nd argument
            expect(function() {
                toast.drminfo.getSdiId(function(){}, []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(function(){}, new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(function(){}, 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(function(){}, {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdiId(function(){}, false);
            }).toThrowError(TypeError);
        });
    });
});
<commit_msg>rollback spec.......<commit_after>/* globals helper */
describe('toast.drminfo', function() {
    it('should be defined as "toast.drminfo" namespace.', function() {
        expect(window.toast).toBeDefined();
        expect(window.toast.drminfo).toBeDefined();
    });
    it('should contain a "getEsn" function.', function() {
        expect(window.toast.drminfo.getEsn).toBeDefined();
        expect(typeof window.toast.drminfo.getEsn).toBe('function');
    });
    it('should contain a "getSdi" function.', function() {
        expect(window.toast.drminfo.getSdi).toBeDefined();
        expect(typeof window.toast.drminfo.getSdi).toBe('function');
    });
    it('should not contain a property that is not exists in the specs.', function() {
        for (var prop in toast.drminfo) {
            expect([
                'getEsn',
                'getSdi'
            ].indexOf(prop) >= 0).toBeTruthy();
        }
    });
    describe('toast.drminfo.getEsn', function() {
        it('returns Esn value as string', function (done) {
            var esn = null;
            toast.drminfo.getEsn('WIDEVINE', function(value){
                esn = value;
                expect(esn).toBeDefined();
                expect(typeof esn).toBe('string');
                done();
            }, function(){
                done.fail();
            });
        }, 3000);
        it('throws TypeError when given arguments is not matched to spec.', function() {
            // no argument
            expect(function() {
                toast.drminfo.getEsn();
            }).toThrowError(TypeError);

            // invalid type for 1st argument
            expect(function() {
                toast.drminfo.getEsn([]);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(function () {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn({});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn(false);
            }).toThrowError(TypeError);

            // invalid type for 2nd argument
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', false);
            }).toThrowError(TypeError);

            // invalid type for 3rd argument
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getEsn('WIDEVINE', function(){}, false);
            }).toThrowError(TypeError);
        });
    });
    describe('toast.drminfo.getSdi', function() {
        it('returns SDI(Samsung Device Identifier) as string', function (done) {
            var sdi = null;
            toast.drminfo.getSdi(function(value){
                sdi = value;
                expect(sdi).toBeDefined();
                expect(typeof sdi).toBe('string');
                done();
            }, function(){
                done.fail();
            });
        }, 3000);
        it('throws TypeError when given arguments is not matched to spec.', function() {
            // no argument
            expect(function() {
                toast.drminfo.getSdi();
            }).toThrowError(TypeError);

            // invalid type for 1st argument
            expect(function() {
                toast.drminfo.getSdi([]);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi({});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(false);
            }).toThrowError(TypeError);

            // invalid type for 2nd argument
            expect(function() {
                toast.drminfo.getSdi(function(){}, []);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(function(){}, new Date());
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(function(){}, 0);
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(function(){}, {});
            }).toThrowError(TypeError);
            expect(function() {
                toast.drminfo.getSdi(function(){}, false);
            }).toThrowError(TypeError);
        });
    });
});
<|endoftext|>


<commit_before>exports.names = ['.afk', '.afkdjs'];
exports.hidden = true;
exports.enabled = true;
exports.matchStart = false;
exports.handler = function (data) {
    if (data.from.role > 1 && config.activeDJTimeoutMins > 0) {

        var maxIdleTime = config.activeDJTimeoutMins * 60;
        idleDJs = [];
        z = 0;

        waitlist = bot.getDJs();
        logger.warning(JSON.stringify(waitlist, null, 2));

        Promise.map(bot.getWaitList(), function (dj) {
            return User.find({where: {id: dj.id}}).on('success', function (dbUser) {
                var position = bot.getWaitListPosition(dj.id);
                if (dbUser !== null) {
                    if (secondsSince(dbUser.last_active) >= maxIdleTime && moment.utc().isAfter(moment.utc(startupTimestamp).add(config.activeDJTimeoutMins, 'minutes'))) {
                        logger.warning('[IDLE]', position + '. ' + dbUser.username + ' last active ' + timeSince(dbUser.last_active));
                        idleDJs.push(dbUser.username);

                    }
                    else {
                        logger.info('[ACTIVE]', position + '. ' + dbUser.username + ' last active ' + timeSince(dbUser.last_active));
                    }
                }
            });
        }).then(function () {
            if (idleDJs.length > 0) {
                var idleDJsList = idleDJs.join(' • ');
                bot.sendChat("Currently idle: " + idleDJsList);
            }
            else {
                bot.sendChat("Everyone's currently active! :thumbsup:");
            }
        });
    }
}<commit_msg>Add ability for mod to reset idle timer for a user (chat splits are awsm)<commit_after>exports.names = ['.afk', '.afkdjs'];
exports.hidden = true;
exports.enabled = true;
exports.matchStart = false;
exports.handler = function (data) {

    var input = data.message.split(' ');

    if (data.from.role > 1 && config.activeDJTimeoutMins > 0) {

        if (input.length >= 2) {
            username = _.initial(username, 1).join(' ').trim();
            var usernameFormatted = S(username).chompLeft('@').s;

            User.update({last_active: new Date(), last_seen: new Date()}, {where: {username: usernameFormatted}});
            bot.sendChat("/me reset the idle timer for " + usernameFormatted);

        }
        else {
            var maxIdleTime = config.activeDJTimeoutMins * 60;
            idleDJs = [];
            z = 0;

            waitlist = bot.getDJs();
            logger.warning(JSON.stringify(waitlist, null, 2));

            Promise.map(bot.getWaitList(), function (dj) {
                return User.find({where: {id: dj.id}}).on('success', function (dbUser) {
                    var position = bot.getWaitListPosition(dj.id);
                    if (dbUser !== null) {
                        if (secondsSince(dbUser.last_active) >= maxIdleTime && moment.utc().isAfter(moment.utc(startupTimestamp).add(config.activeDJTimeoutMins, 'minutes'))) {
                            logger.warning('[IDLE]', position + '. ' + dbUser.username + ' last active ' + timeSince(dbUser.last_active));
                            idleDJs.push(dbUser.username);

                        }
                        else {
                            logger.info('[ACTIVE]', position + '. ' + dbUser.username + ' last active ' + timeSince(dbUser.last_active));
                        }
                    }
                });
            }).then(function () {
                if (idleDJs.length > 0) {
                    var idleDJsList = idleDJs.join(' • ');
                    bot.sendChat("Currently idle: " + idleDJsList);
                }
                else {
                    bot.sendChat("Everyone's currently active! :thumbsup:");
                }
            });
        }
    }
}<|endoftext|>


<commit_before>export function t(i18nString, locale, fallback) {
  return i18nString && (i18nString[locale] || i18nString[fallback||'en'] || '')
}
<commit_msg>fix t function<commit_after>import {isString} from 'lodash'

export function t(i18nString, locale, fallback) {
  if (isString(i18nString)) {
    return i18nString
  }
  return i18nString && (i18nString[locale] || i18nString[fallback||'en'] || '')
}
<|endoftext|>


<commit_before>// @flow

import React, { PropTypes } from 'react';
import {
  Animated,
  BackAndroid,
  Easing,
  PixelRatio,
  Platform,
  StyleSheet,
  Text,
  NativeModules,
  TouchableOpacity,
  TouchableNativeFeedback,
  TouchableWithoutFeedback,
  View,
} from 'react-native';

// Not everybody has this enabled yet
const useNativeDriver = !!NativeModules.NativeAnimatedModule;

type ActionSheetOptions = {
  options: Array<string>,
  destructiveButtonIndex: ?number,
  cancelButtonIndex: ?number,
}

type ActionGroupProps = {
  options: Array<string>,
  destructiveButtonIndex: ?number,
  onSelect: (i: number) => boolean,
  startIndex: number,
  length: number,
}

type ActionSheetState = {
  isVisible: boolean,
  isAnimating: boolean,
  options: ?ActionSheetOptions,
  onSelect: ?(i: number) => void,
  overlayOpacity: any,
  sheetOpacity: any,
}

type ActionSheetProps = {
  children: ?any,
}

const OPACITY_ANIMATION_TIME = 150;
const PIXEL = 1 / PixelRatio.get();

class ActionGroup extends React.Component {
  props: ActionGroupProps;

  static propTypes = {
    options: PropTypes.array.isRequired,
    destructiveButtonIndex: PropTypes.number,
    onSelect: PropTypes.func.isRequired,
    startIndex: PropTypes.number.isRequired,
    length: PropTypes.number.isRequired,
  };

  render() {
    let {
      options,
      destructiveButtonIndex,
      onSelect,
      startIndex,
      length,
    } = this.props;

    let optionViews = [];

    let nativeFeedbackBackground = TouchableNativeFeedbackSafe.Ripple(
      'rgba(180, 180, 180, 1)',
      false
    );

    for (let i = startIndex; i < startIndex + length; i++) {
      let color = '#444444';
      if (i === destructiveButtonIndex) {
        color = '#ff3b30';
      }

      optionViews.push(
        <TouchableNativeFeedbackSafe
          key={i}
          pressInDelay={0}
          background={nativeFeedbackBackground}
          onPress={() => onSelect(i)}
          style={styles.button}>
          <Text style={[styles.text, {color}]}>
            {options[i]}
          </Text>
        </TouchableNativeFeedbackSafe>
      );

      if (i < startIndex + length - 1) {
        optionViews.push(
          <View key={`separator-${i}`} style={styles.rowSeparator} />
        );
      }
    }

    return (
      <View style={styles.groupContainer}>
        {optionViews}
      </View>
    );
  }
}

// Has same API as https://facebook.github.io/react-native/docs/actionsheetios.html
export default class ActionSheet extends React.Component {
  props: ActionSheetProps;
  _animateOutCallback: ?() => void = null;

  state: ActionSheetState = {
    isVisible: false,
    isAnimating: false,
    options: null,
    onSelect: null,
    overlayOpacity: new Animated.Value(0),
    sheetOpacity: new Animated.Value(0),
  };

  render() {
    let { isVisible } = this.state;
    let overlay = isVisible ? (
      <Animated.View style={[styles.overlay, {
        opacity: this.state.overlayOpacity,
      }]} />
    ) : null;

    let sheet = isVisible ? this._renderSheet() : null;

    return (
      <View style={{flex: 1}}>
        {React.Children.only(this.props.children)}
        {overlay}
        {sheet}
      </View>
    );
  }

  _renderSheet() {
    if (!this.state.options) {
      return;
    }

    let numOptions = this.state.options.options.length;

    return (
      <TouchableWithoutFeedback onPress={this._selectCancelButton}>
        <Animated.View
          needsOffscreenAlphaCompositing={this.state.isAnimating}
          style={[styles.sheetContainer, {
            opacity: this.state.sheetOpacity,
            transform: [{scale: this.state.sheetOpacity.interpolate({inputRange: [0, 0.5, 1], outputRange: [0.6, 1, 1]})}],
          }]}>
          <View style={styles.sheet}>
            <ActionGroup
              options={this.state.options.options}
              destructiveButtonIndex={this.state.options.destructiveButtonIndex}
              onSelect={this._onSelect}
              startIndex={0}
              length={numOptions}
            />
          </View>
        </Animated.View>
      </TouchableWithoutFeedback>
    );
  }

  showActionSheetWithOptions(
    options: ActionSheetOptions,
    onSelect: (i: number) => void,
    onAnimateOut: () => void
  ) {
    if (this.state.isVisible) {
      return;
    }

    this.setState({
      options,
      onSelect,
      isVisible: true,
      isAnimating: true,
    });

    this.state.overlayOpacity.setValue(0);
    this.state.sheetOpacity.setValue(0);

    Animated.parallel([
      Animated.timing(this.state.overlayOpacity, {
        toValue: 0.5,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
      Animated.timing(this.state.sheetOpacity, {
        toValue: 1,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
    ]).start(result => {
      if (result.finished) {
        this.setState({
          isAnimating: false,
        });
      }
    });

    this._animateOutCallback = onAnimateOut;

    BackAndroid.addEventListener('actionSheetHardwareBackPress', this._selectCancelButton);
  }

  _selectCancelButton = () => {
    if (!this.state.options) {
      return;
    }

    if (typeof this.state.options.cancelButtonIndex === 'number') {
      return this._onSelect(this.state.options.cancelButtonIndex);
    } else {
      return this._animateOut();
    }
  }

  _onSelect = (index: number): boolean => {
    if (this.state.isAnimating) {
      return false;
    }

    this.state.onSelect && this.state.onSelect(index);
    return this._animateOut();
  }

  _animateOut = (): boolean => {
    if (this.state.isAnimating) {
      return false;
    }

    BackAndroid.removeEventListener('actionSheetHardwareBackPress', this._selectCancelButton);

    this.setState({
      isAnimating: true,
    });

    Animated.parallel([
      Animated.timing(this.state.overlayOpacity, {
        toValue: 0,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
      Animated.timing(this.state.sheetOpacity, {
        toValue: 0,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
    ]).start(result => {
      if (result.finished) {
        this.setState({
          isVisible: false,
          isAnimating: false,
        });
        if (typeof this._animateOutCallback === 'function') {
          this._animateOutCallback();
          this._animateOutCallback = null;
        }
      }
    });

    return true;
  }
}

let TouchableComponent;

if (Platform.OS === 'android') {
  TouchableComponent = Platform.Version <= 20 ? TouchableOpacity : TouchableNativeFeedback;
} else {
  TouchableComponent = TouchableOpacity;
}

if (TouchableComponent !== TouchableNativeFeedback) {
  TouchableComponent.SelectableBackground = () => ({});
  TouchableComponent.SelectableBackgroundBorderless = () => ({});
  TouchableComponent.Ripple = (color, borderless) => ({});
}

class TouchableNativeFeedbackSafe extends React.Component {

  static SelectableBackground = TouchableComponent.SelectableBackground;
  static SelectableBackgroundBorderless = TouchableComponent.SelectableBackgroundBorderless;
  static Ripple = TouchableComponent.Ripple;

  render() {
    if (TouchableComponent === TouchableNativeFeedback) {
      return (
        <TouchableComponent {...this.props} style={{}}>
          <View style={this.props.style}>
            {this.props.children}
          </View>
        </TouchableComponent>
      );
    } else {
      return (
        <TouchableComponent {...this.props}>
          {this.props.children}
        </TouchableComponent>
      );
    }
  }
}

let styles = StyleSheet.create({
  groupContainer: {
    backgroundColor: '#fefefe',
    borderRadius: 4,
    borderColor: '#cbcbcb',
    borderWidth: PIXEL,
    overflow: 'hidden',
    marginHorizontal: 16,
    marginBottom: 8,
  },
  button: {
    justifyContent: 'center',
    alignItems: 'flex-start',
    height: 50,
    paddingHorizontal: 16,
  },
  text: {
    fontSize: 17,
    fontWeight: '700',
  },
  rowSeparator: {
    backgroundColor: '#dddddd',
    height: 1,
    flex: 1,
  },
  overlay: {
    position: 'absolute',
    top: 0,
    right: 0,
    bottom: 0,
    left: 0,
    backgroundColor: 'black',
  },
  sheetContainer: {
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 0,
    top: 0,
    backgroundColor: 'transparent',
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
  },
  sheet: {
    flex: 1,
    backgroundColor: 'transparent',
  },
});
<commit_msg>Fix(Android): remove useless code. Closes #16<commit_after>// @flow

import React, { PropTypes } from 'react';
import {
  Animated,
  BackAndroid,
  Easing,
  PixelRatio,
  Platform,
  StyleSheet,
  Text,
  Image,
  NativeModules,
  TouchableOpacity,
  TouchableNativeFeedback,
  TouchableWithoutFeedback,
  View,
} from 'react-native';

// Not everybody has this enabled yet
const useNativeDriver = !!NativeModules.NativeAnimatedModule;

type ActionSheetOptions = {
  options: Array<string>,
  icons: ?Array<number>,
  destructiveButtonIndex: ?number,
  cancelButtonIndex: ?number,
}

type ActionGroupProps = {
  options: Array<string>,
  icons: ?Array<number>,
  destructiveButtonIndex: ?number,
  onSelect: (i: number) => boolean,
  startIndex: number,
  length: number,
}

type ActionSheetState = {
  isVisible: boolean,
  isAnimating: boolean,
  options: ?ActionSheetOptions,
  onSelect: ?(i: number) => void,
  overlayOpacity: any,
  sheetOpacity: any,
}

type ActionSheetProps = {
  children: ?any,
}

const OPACITY_ANIMATION_TIME = 150;
const PIXEL = 1 / PixelRatio.get();

class ActionGroup extends React.Component {
  props: ActionGroupProps;

  static propTypes = {
    options: PropTypes.array.isRequired,
    icons: PropTypes.array,
    destructiveButtonIndex: PropTypes.number,
    onSelect: PropTypes.func.isRequired,
    startIndex: PropTypes.number.isRequired,
    length: PropTypes.number.isRequired,
  };

  render() {
    let {
      options,
      icons,
      destructiveButtonIndex,
      onSelect,
      startIndex,
      length,
    } = this.props;

    let optionViews = [];

    let nativeFeedbackBackground = TouchableNativeFeedbackSafe.Ripple(
      'rgba(180, 180, 180, 1)',
      false
    );

    for (let i = startIndex; i < startIndex + length; i++) {
      let color = '#444444';
      if (i === destructiveButtonIndex) {
        color = '#ff3b30';
      }

      let iconElement = undefined

      if (icons && icons[i]) {
        iconElement = (
          <Image
            source={icons[i]}
            style={styles.icon}
          />
          )
      }

      optionViews.push(
        <TouchableNativeFeedbackSafe
          key={i}
          pressInDelay={0}
          background={nativeFeedbackBackground}
          onPress={() => onSelect(i)}
          style={styles.button}>
          {iconElement}
          <Text style={[styles.text, {color}]}>
            {options[i]}
          </Text>
        </TouchableNativeFeedbackSafe>
      );

      if (i < startIndex + length - 1) {
        optionViews.push(
          <View key={`separator-${i}`} style={styles.rowSeparator} />
        );
      }
    }

    return (
      <View style={styles.groupContainer}>
        {optionViews}
      </View>
    );
  }
}

// Has same API as https://facebook.github.io/react-native/docs/actionsheetios.html
export default class ActionSheet extends React.Component {
  props: ActionSheetProps;
  _animateOutCallback: ?() => void = null;

  state: ActionSheetState = {
    isVisible: false,
    isAnimating: false,
    options: null,
    onSelect: null,
    overlayOpacity: new Animated.Value(0),
    sheetOpacity: new Animated.Value(0),
  };

  render() {
    let { isVisible } = this.state;
    let overlay = isVisible ? (
      <Animated.View style={[styles.overlay, {
        opacity: this.state.overlayOpacity,
      }]} />
    ) : null;

    let sheet = isVisible ? this._renderSheet() : null;

    return (
      <View style={{flex: 1}}>
        {React.Children.only(this.props.children)}
        {overlay}
        {sheet}
      </View>
    );
  }

  _renderSheet() {
    if (!this.state.options) {
      return;
    }

    let numOptions = this.state.options.options.length;

    return (
      <TouchableWithoutFeedback onPress={this._selectCancelButton}>
        <Animated.View
          needsOffscreenAlphaCompositing={this.state.isAnimating}
          style={[styles.sheetContainer, {
            opacity: this.state.sheetOpacity,
            transform: [{scale: this.state.sheetOpacity.interpolate({inputRange: [0, 0.5, 1], outputRange: [0.6, 1, 1]})}],
          }]}>
          <View style={styles.sheet}>
            <ActionGroup
              options={this.state.options.options}
              icons={this.state.options.icons}
              destructiveButtonIndex={this.state.options.destructiveButtonIndex}
              onSelect={this._onSelect}
              startIndex={0}
              length={numOptions}
            />
          </View>
        </Animated.View>
      </TouchableWithoutFeedback>
    );
  }

  showActionSheetWithOptions(
    options: ActionSheetOptions,
    onSelect: (i: number) => void,
    onAnimateOut: () => void
  ) {
    if (this.state.isVisible) {
      return;
    }

    this.setState({
      options,
      onSelect,
      isVisible: true,
      isAnimating: true,
    });

    this.state.overlayOpacity.setValue(0);
    this.state.sheetOpacity.setValue(0);

    Animated.parallel([
      Animated.timing(this.state.overlayOpacity, {
        toValue: 0.5,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
      Animated.timing(this.state.sheetOpacity, {
        toValue: 1,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
    ]).start(result => {
      if (result.finished) {
        this.setState({
          isAnimating: false,
        });
      }
    });

    this._animateOutCallback = onAnimateOut;

    BackAndroid.addEventListener('actionSheetHardwareBackPress', this._selectCancelButton);
  }

  _selectCancelButton = () => {
    if (!this.state.options) {
      return false;
    }

    if (typeof this.state.options.cancelButtonIndex === 'number') {
      return this._onSelect(this.state.options.cancelButtonIndex);
    } else {
      return this._animateOut();
    }
  }

  _onSelect = (index: number): boolean => {
    if (this.state.isAnimating) {
      return false;
    }

    this.state.onSelect && this.state.onSelect(index);
    return this._animateOut();
  }

  _animateOut = (): boolean => {
    if (this.state.isAnimating) {
      return false;
    }

    BackAndroid.removeEventListener('actionSheetHardwareBackPress', this._selectCancelButton);

    this.setState({
      isAnimating: true,
    });

    Animated.parallel([
      Animated.timing(this.state.overlayOpacity, {
        toValue: 0,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
      Animated.timing(this.state.sheetOpacity, {
        toValue: 0,
        easing: Easing.in(Easing.linear),
        duration: OPACITY_ANIMATION_TIME,
        useNativeDriver,
      }),
    ]).start(result => {
      if (result.finished) {
        this.setState({
          isVisible: false,
          isAnimating: false,
        });
        if (typeof this._animateOutCallback === 'function') {
          this._animateOutCallback();
          this._animateOutCallback = null;
        }
      }
    });

    return true;
  }
}

let TouchableComponent;

TouchableComponent = Platform.Version <= 20 ? TouchableOpacity : TouchableNativeFeedback;

if (TouchableComponent !== TouchableNativeFeedback) {
  TouchableComponent.SelectableBackground = () => ({});
  TouchableComponent.SelectableBackgroundBorderless = () => ({});
  TouchableComponent.Ripple = (color, borderless) => ({});
}

class TouchableNativeFeedbackSafe extends React.Component {

  static SelectableBackground = TouchableComponent.SelectableBackground;
  static SelectableBackgroundBorderless = TouchableComponent.SelectableBackgroundBorderless;
  static Ripple = TouchableComponent.Ripple;

  render() {
    if (TouchableComponent === TouchableNativeFeedback) {
      return (
        <TouchableComponent {...this.props} style={{}}>
          <View style={this.props.style}>
            {this.props.children}
          </View>
        </TouchableComponent>
      );
    } else {
      return (
        <TouchableComponent {...this.props}>
          {this.props.children}
        </TouchableComponent>
      );
    }
  }
}

let styles = StyleSheet.create({
  groupContainer: {
    backgroundColor: '#fefefe',
    borderRadius: 4,
    borderColor: '#cbcbcb',
    borderWidth: PIXEL,
    overflow: 'hidden',
    marginHorizontal: 16,
    marginBottom: 8,
  },
  button: {
    justifyContent: 'flex-start',
    alignItems: 'center',
    flexDirection: 'row',
    height: 50,
    paddingHorizontal: 16,
  },
  icon: {
    marginRight: 15,
  },
  text: {
    fontSize: 17,
    fontWeight: '700',
  },
  rowSeparator: {
    backgroundColor: '#dddddd',
    height: 1,
    flex: 1,
  },
  overlay: {
    position: 'absolute',
    top: 0,
    right: 0,
    bottom: 0,
    left: 0,
    backgroundColor: 'black',
  },
  sheetContainer: {
    position: 'absolute',
    left: 0,
    right: 0,
    bottom: 0,
    top: 0,
    backgroundColor: 'transparent',
    alignItems: 'center',
    justifyContent: 'center',
    flexDirection: 'row',
  },
  sheet: {
    flex: 1,
    backgroundColor: 'transparent',
  },
});
<|endoftext|>


<commit_before><commit_msg>adding more link ref<commit_after><|endoftext|>


<commit_before>/*exported Camera*/
var Camera = (function() {
  'use strict';

  var DEG_TO_RAD = Math.PI / 180;

  function Camera( fov, aspect, near, far ) {
    this.fov = fov || 60;
    this.aspect = aspect || 1;
    this.near = near || 0.1;
    this.far = far || 1000;

    this.matrix = new Float32Array( 16 );
  }

  Camera.prototype.updateProjectionMatrix = function() {
    var near = this.near,
        far  = this.far;

    var top    = near * Math.tan( this.fov * 0.5 * DEG_TO_RAD ),
        bottom = -top,
        left   = bottom * this.aspect,
        right  = top * this.aspect;

    var x = 2 * near / ( right - left ),
        y = 2 * near / ( top - bottom );

    var a = ( right + left ) / ( right - left ),
        b = ( top + bottom ) / ( top - bottom ),
        c = -( far + near ) / ( far - near ),
        d = -2 * far * near / ( far - near );

    var m = this.matrix;

    m[  0 ] = x;
    m[  1 ] = 0;
    m[  2 ] = 0;
    m[  3 ] = 0;
    m[  4 ] = 0;
    m[  5 ] = y;
    m[  6 ] = 0;
    m[  7 ] = 0;
    m[  8 ] = a;
    m[  9 ] = b;
    m[ 10 ] = c;
    m[ 11 ] = -1;
    m[ 12 ] = 0;
    m[ 13 ] = 0;
    m[ 14 ] = d;
    m[ 15 ] = 0;

    return this;
  };

  Camera.prototype.transform = function( x, y, z ) {
    var m = this.matrix;

    return [
      m[ 0 ] * x + m[ 4 ] * y + m[  8 ] * z + m[ 12 ],
      m[ 1 ] * x + m[ 5 ] * y + m[  9 ] * z + m[ 13 ],
      m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z + m[ 14 ]
    ];
  };

  return Camera;

}) ();
<commit_msg>tunnel: Add Camera perspective projection.<commit_after>/*exported Camera*/
var Camera = (function() {
  'use strict';

  var DEG_TO_RAD = Math.PI / 180;

  function Camera( fov, aspect, near, far ) {
    this.fov = fov || 60;
    this.aspect = aspect || 1;
    this.near = near || 0.1;
    this.far = far || 1000;

    this.matrix = new Float32Array( 16 );
  }

  Camera.prototype.updateProjectionMatrix = function() {
    var near = this.near,
        far  = this.far;

    var top    = near * Math.tan( this.fov * 0.5 * DEG_TO_RAD ),
        bottom = -top,
        left   = bottom * this.aspect,
        right  = top * this.aspect;

    var x = 2 * near / ( right - left ),
        y = 2 * near / ( top - bottom );

    var a = ( right + left ) / ( right - left ),
        b = ( top + bottom ) / ( top - bottom ),
        c = -( far + near ) / ( far - near ),
        d = -2 * far * near / ( far - near );

    var m = this.matrix;

    m[  0 ] = x;
    m[  1 ] = 0;
    m[  2 ] = 0;
    m[  3 ] = 0;
    m[  4 ] = 0;
    m[  5 ] = y;
    m[  6 ] = 0;
    m[  7 ] = 0;
    m[  8 ] = a;
    m[  9 ] = b;
    m[ 10 ] = c;
    m[ 11 ] = -1;
    m[ 12 ] = 0;
    m[ 13 ] = 0;
    m[ 14 ] = d;
    m[ 15 ] = 0;

    return this;
  };

  Camera.prototype.transform = function( x, y, z ) {
    var m = this.matrix;

    return [
      m[ 0 ] * x + m[ 4 ] * y + m[  8 ] * z + m[ 12 ],
      m[ 1 ] * x + m[ 5 ] * y + m[  9 ] * z + m[ 13 ],
      m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z + m[ 14 ]
    ];
  };

  Camera.prototype.project = function( x, y, z ) {
    var m = this.matrix;
    var d = 1 / ( m[ 3 ] * x + m[ 7 ] * y + m[ 11 ] * z + m[ 15 ] );

    return [
      ( m[ 0 ] * x + m[ 4 ] * y + m[  8 ] * z + m[ 12 ] ) * d,
      ( m[ 1 ] * x + m[ 5 ] * y + m[  9 ] * z + m[ 13 ] ) * d,
      ( m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z + m[ 14 ] ) * d
    ];
  };

  return Camera;

}) ();
<|endoftext|>


<commit_before>var extract = require('i18n-extract');
const fs = require('fs');

var path = '../app/dist/locales/en.json';

fs.writeFile(path, '{}', 'utf8', function(err) {
    if(err) {
        return console.log(err);
    }
    var enLocale = require(path);

    const keys = extract.extractFromFiles(['js/**/*.{js,jsx}'], {
    marker: '__',
    });

    let reports = [];
    reports = reports.concat(extract.findMissing(enLocale, keys));

    if (reports.length > 0) {
        fs.readFile(path, 'utf8', function readFileCallback(err, data){
            if (err){
                console.log(err);
            } else {
                localeObj = JSON.parse(data);

                for (var i = 0; i < reports.length; i++) {
                    // no need to care for other types than MISSING because starting file will always be empty
                    if (reports[i].type === 'MISSING') {
                        localeObj[reports[i].key] = reports[i].key;
                    }
                }

                var json = JSON.stringify(localeObj, null, '\t'); //convert it back to json-string
                fs.writeFile(path, json, 'utf8', function callback(err) {
                    if (err) throw err;
                    console.log('Extracted all strings!');
                });
            }
        });
    }
});

<commit_msg>create locales dir if it doesnt exist<commit_after>var extract = require("i18n-extract");
const fs = require("fs");

var dir = __dirname + "/../app/dist/locales";
var path = dir + "/en.json";

if (!fs.existsSync(dir)) {
  fs.mkdirSync(dir);
}

fs.writeFile(path, "{}", "utf8", function(err) {
  if (err) {
    return console.log(err);
  }
  var enLocale = require(path);

  const keys = extract.extractFromFiles(["js/**/*.{js,jsx}"], {
    marker: "__",
  });

  let reports = [];
  reports = reports.concat(extract.findMissing(enLocale, keys));

  if (reports.length > 0) {
    fs.readFile(path, "utf8", function readFileCallback(err, data) {
      if (err) {
        console.log(err);
      } else {
        localeObj = JSON.parse(data);

        for (var i = 0; i < reports.length; i++) {
          // no need to care for other types than MISSING because starting file will always be empty
          if (reports[i].type === "MISSING") {
            localeObj[reports[i].key] = reports[i].key;
          }
        }

        var json = JSON.stringify(localeObj, null, "\t"); //convert it back to json-string
        fs.writeFile(path, json, "utf8", function callback(err) {
          if (err) {
            throw err;
          }
          console.log("Extracted all strings!");
        });
      }
    });
  }
});
<|endoftext|>


<commit_before>const gulp = require('gulp');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const colors = require('ansi-colors');
const logger = require('fancy-log');
const watchify = require('watchify');
const browserify = require('browserify');
const uglify = require('gulp-uglify');
const size = require('gulp-size');
const tsify = require('tsify');
const concat = require('gulp-concat');
const exec = require('child_process').exec;
const fs = require('fs');

require('../gulp/cssProject.js')(__dirname);

const browserifyOpts = (entries, debug) => ({
  entries: entries,
  standalone: 'Lichess',
  debug: debug
});
const destinationPath = '../../public/compiled/';
const destination = () => gulp.dest(destinationPath);
const fileBaseName = 'lichess.site';

const abFile = process.env.LILA_AB_FILE;

const jqueryFill = () => gulp.src('src/jquery.fill.js')
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const ab = () => {
  if (abFile) return gulp.src(abFile)
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
  else {
    logger.info(colors.yellow('Building without AB file'));
    return gulp.src('.');
  }
};

const stockfishPexe = () => gulp.src([
  require.resolve('stockfish.pexe/stockfish.nmf'),
  require.resolve('stockfish.pexe/stockfish.pexe'),
  require.resolve('stockfish.pexe/stockfish.bc')
]).pipe(gulp.dest('../../public/vendor/stockfish.pexe'));

const stockfishJs = () => gulp.src([
  require.resolve('stockfish.js/stockfish.wasm.js'),
  require.resolve('stockfish.js/stockfish.wasm'),
  require.resolve('stockfish.js/stockfish.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.js'));

const stockfishWasm = () => gulp.src([
  require.resolve('stockfish.wasm/stockfish.js'),
  require.resolve('stockfish.wasm/stockfish.js.mem'),
  require.resolve('stockfish.wasm/stockfish.wasm'),
  require.resolve('stockfish.wasm/stockfish.worker.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.wasm/'));

const stockfishMvWasm = () => gulp.src([
  require.resolve('stockfish-mv.wasm/stockfish.js'),
  require.resolve('stockfish-mv.wasm/stockfish.js.mem'),
  require.resolve('stockfish-mv.wasm/stockfish.wasm'),
  require.resolve('stockfish-mv.wasm/pthread-main.js')
]).pipe(gulp.dest('../../public/vendor/stockfish-mv.wasm/'));

const prodSource = () => browserify(browserifyOpts('src/index.ts', false))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.source.min.js`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const devSource = () => browserify(browserifyOpts('src/index.ts', true))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.js`))
  .pipe(destination());

function makeDependencies(filename) {
  return function bundleDeps() {
    return gulp.src([
  '../../public/javascripts/vendor/jquery.min.js',
  './dist/jquery.fill.js',
  './dep/powertip.min.js',
  './dep/howler.min.js',
  './dep/mousetrap.min.js',
  './dist/consolemsg.js',
  ...(abFile ? ['./dist/ab.js'] : []),
])
      .pipe(concat(filename))
      .pipe(destination());
  };
}

function makeBundle(filename) {
  return function bundleItAll() {
    return gulp.src([
      destinationPath + 'lichess.deps.js',
      './dist/' + filename,
    ])
      .pipe(concat(filename.replace('source.', '')))
      .pipe(destination());
  };
}

const gitSha = (cb) => exec("git rev-parse -q --short HEAD", function (err, stdout) {
  if (err) throw err;
  if (!fs.existsSync('./dist')) fs.mkdirSync('./dist');
  var date = new Date().toISOString().split('.')[0];
  fs.writeFileSync('./dist/consolemsg.js',
    'window.lichess=window.lichess||{};console.info("Lichess is open source! https://github.com/ornicar/lila");' +
    `lichess.info = "Assets built ${date} from sha ${stdout.trim()}";`);
  cb();
});

const standalonesJs = () => gulp.src([
  'util.js', 'trans.js', 'tv.js', 'puzzle.js', 'user.js', 'coordinate.js', 'captcha.js', 'embed-analyse.js'
].map(f => `src/standalones/${f}`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const userMod = () => browserify(browserifyOpts('./src/user-mod.js', false))
  .bundle()
  .pipe(source('user-mod.js'))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const tasks = [gitSha, jqueryFill, ab, standalonesJs, userMod, stockfishWasm, stockfishMvWasm, stockfishPexe, stockfishJs];

const dev = gulp.series(tasks.concat([devSource]));

const deps = makeDependencies('lichess.deps.js');

gulp.task('prod', gulp.series(tasks, deps, prodSource, makeBundle(`${fileBaseName}.source.min.js`)));
gulp.task('dev', dev, deps);
gulp.task('default', gulp.series(dev, deps, () => gulp.watch('src/**/*.js', dev)));

gulp.task('deps', gulp.series(tasks, deps));
<commit_msg>fix site gulpfile<commit_after>const gulp = require('gulp');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
const colors = require('ansi-colors');
const logger = require('fancy-log');
const watchify = require('watchify');
const browserify = require('browserify');
const uglify = require('gulp-uglify');
const size = require('gulp-size');
const tsify = require('tsify');
const concat = require('gulp-concat');
const exec = require('child_process').exec;
const fs = require('fs');

require('../gulp/cssProject.js')(__dirname);

const browserifyOpts = (entries, debug) => ({
  entries: entries,
  standalone: 'Lichess',
  debug: debug
});
const destinationPath = '../../public/compiled/';
const destination = () => gulp.dest(destinationPath);
const fileBaseName = 'lichess.site';

const abFile = process.env.LILA_AB_FILE;

const jqueryFill = () => gulp.src('src/jquery.fill.js')
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const ab = () => {
  if (abFile) return gulp.src(abFile)
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest('./dist'));
  else {
    logger.info(colors.yellow('Building without AB file'));
    return gulp.src('.');
  }
};

const stockfishPexe = () => gulp.src([
  require.resolve('stockfish.pexe/stockfish.nmf'),
  require.resolve('stockfish.pexe/stockfish.pexe'),
  require.resolve('stockfish.pexe/stockfish.bc')
]).pipe(gulp.dest('../../public/vendor/stockfish.pexe'));

const stockfishJs = () => gulp.src([
  require.resolve('stockfish.js/stockfish.wasm.js'),
  require.resolve('stockfish.js/stockfish.wasm'),
  require.resolve('stockfish.js/stockfish.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.js'));

const stockfishWasm = () => gulp.src([
  require.resolve('stockfish.wasm/stockfish.js'),
  require.resolve('stockfish.wasm/stockfish.js.mem'),
  require.resolve('stockfish.wasm/stockfish.wasm'),
  require.resolve('stockfish.wasm/stockfish.worker.js')
]).pipe(gulp.dest('../../public/vendor/stockfish.wasm/'));

const stockfishMvWasm = () => gulp.src([
  require.resolve('stockfish-mv.wasm/stockfish.js'),
  require.resolve('stockfish-mv.wasm/stockfish.js.mem'),
  require.resolve('stockfish-mv.wasm/stockfish.wasm'),
  require.resolve('stockfish-mv.wasm/pthread-main.js')
]).pipe(gulp.dest('../../public/vendor/stockfish-mv.wasm/'));

const prodSource = () => browserify(browserifyOpts('src/index.ts', false))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.source.min.js`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(gulp.dest('./dist'));

const devSource = () => browserify(browserifyOpts('src/index.ts', true))
  .plugin(tsify)
  .bundle()
  .pipe(source(`${fileBaseName}.js`))
  .pipe(destination());

function makeDependencies(filename) {
  return function bundleDeps() {
    return gulp.src([
  '../../public/javascripts/vendor/jquery.min.js',
  './dist/jquery.fill.js',
  './dep/powertip.min.js',
  './dep/howler.min.js',
  './dep/mousetrap.min.js',
  './dist/consolemsg.js',
  ...(abFile ? ['./dist/ab.js'] : []),
])
      .pipe(concat(filename))
      .pipe(destination());
  };
}

function makeBundle(filename) {
  return function bundleItAll() {
    return gulp.src([
      destinationPath + 'lichess.deps.js',
      './dist/' + filename,
    ])
      .pipe(concat(filename.replace('source.', '')))
      .pipe(destination());
  };
}

const gitSha = (cb) => exec("git rev-parse -q --short HEAD", function (err, stdout) {
  if (err) throw err;
  if (!fs.existsSync('./dist')) fs.mkdirSync('./dist');
  var date = new Date().toISOString().split('.')[0];
  fs.writeFileSync('./dist/consolemsg.js',
    'window.lichess=window.lichess||{};console.info("Lichess is open source! https://github.com/ornicar/lila");' +
    `lichess.info = "Assets built ${date} from sha ${stdout.trim()}";`);
  cb();
});

const standalonesJs = () => gulp.src([
  'util.js', 'trans.js', 'tv.js', 'puzzle.js', 'user.js', 'coordinate.js', 'captcha.js', 'embed-analyse.js'
].map(f => `src/standalones/${f}`))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const userMod = () => browserify(browserifyOpts('./src/user-mod.js', false))
  .bundle()
  .pipe(source('user-mod.js'))
  .pipe(buffer())
  .pipe(uglify())
  .pipe(destination());

const tasks = [gitSha, jqueryFill, ab, standalonesJs, userMod, stockfishWasm, stockfishMvWasm, stockfishPexe, stockfishJs];

const dev = gulp.series(tasks.concat([devSource]));

const deps = makeDependencies('lichess.deps.js');

gulp.task('prod', gulp.series(tasks, deps, prodSource, makeBundle(`${fileBaseName}.source.min.js`)));
gulp.task('dev', gulp.series(deps, dev));
gulp.task('default', gulp.series(deps, dev, () => gulp.watch('src/**/*.js', dev)));

gulp.task('deps', gulp.series(tasks, deps));
<|endoftext|>


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

module.exports = {
    db: process.env.MONGODB || 'mongodb://localhost:27017/info',
    geocode: secret.geocode || process.env.GEOCODE,
    geopoints: secret.geopoints || process.env.GEOPOINTS,
    cityinfo: secret.cityinfo || process.env.CITYINFO,
    cities: [{
        name: 'Москва',
        regionId: 213
    }, {
        name: 'Санкт-Петербург',
        regionId: 10174
    }, {
        name: 'Ростов-на-Дону',
        regionId: 11029
    }, {
        name: 'Новосибирск',
        regionId: 11316
    }, {
        name: 'Екатеринбург',
        regionId: 11162
    }, {
        name: 'Нижний Новгород',
        regionId: 11079
    }, {
        name: 'Казань',
        regionId: 11119
    }, {
        name: 'Самара',
        regionId: 11131
    }, {
        name: 'Челябинск',
        regionId: 11225
    }, {
        name: 'Омск',
        regionId: 11318
    }, {
        name: 'Уфа',
        regionId: 11111
    }, {
        name: 'Красноярск',
        regionId: 11309
    }, {
        name: 'Пермь',
        regionId: 11108
    }, {
        name: 'Волгоград',
        regionId: 10950
    }, {
        name: 'Воронеж',
        regionId: 10672
    }, {
        name: 'Саратов',
        regionId: 11146
    }, {
        name: 'Краснодар',
        regionId: 10995
    }],
    tasks: [{
        cron: '0 0 * * * *',
        name: 'getInfo'
    }]
};<commit_msg>changing config for cron sheduler<commit_after>var secret = require('./secret');

module.exports = {
    db: process.env.MONGODB || 'mongodb://localhost:27017/info',
    geocode: secret.geocode || process.env.GEOCODE,
    geopoints: secret.geopoints || process.env.GEOPOINTS,
    cityinfo: secret.cityinfo || process.env.CITYINFO,
    cities: [{
        name: 'Москва',
        regionId: 213
    }, {
        name: 'Санкт-Петербург',
        regionId: 10174
    }, {
        name: 'Ростов-на-Дону',
        regionId: 11029
    }, {
        name: 'Новосибирск',
        regionId: 11316
    }, {
        name: 'Екатеринбург',
        regionId: 11162
    }, {
        name: 'Нижний Новгород',
        regionId: 11079
    }, {
        name: 'Казань',
        regionId: 11119
    }, {
        name: 'Самара',
        regionId: 11131
    }, {
        name: 'Челябинск',
        regionId: 11225
    }, {
        name: 'Омск',
        regionId: 11318
    }, {
        name: 'Уфа',
        regionId: 11111
    }, {
        name: 'Красноярск',
        regionId: 11309
    }, {
        name: 'Пермь',
        regionId: 11108
    }, {
        name: 'Волгоград',
        regionId: 10950
    }, {
        name: 'Воронеж',
        regionId: 10672
    }, {
        name: 'Саратов',
        regionId: 11146
    }, {
        name: 'Краснодар',
        regionId: 10995
    }],
    tasks: [{
        cron: '0 */20 * * * *',
        name: 'getInfo'
    }]
};<|endoftext|>


<commit_before>module.exports = {
  port: 3000,
  env: 'development'
};
<commit_msg>Change port<commit_after>module.exports = {
  port: 8000,
  env: 'development'
};
<|endoftext|>


<commit_before>// karma.conf.js
module.exports = config => {
    config.set({
        basePath: '../',
        preprocessors: {
            'src/**/*.js': ['babel'],
            '**/src/**/*.js': ['coverage']
        },
        babelPreprocessor: {
            options: {
                presets: ['es2015'],
                sourceMap: 'inline'
            },
            filename: file => {
                return file.originalPath.replace(/\.js$/, '.es5.js');
            },
            sourceFileName: file => {
                return file.originalPath;
            }
        },
        files: [
            'dev/assets/js/vendor.js',
            'src/**/*.js',
            'src/**/*.spec.js'
        ],
        browsers: [
            'PhantomJS',
            'Firefox',
            'Chrome'
        ],
        frameworks: [
            'mocha',
            'chai'
        ],
        autoWatch: false,
        client: {
            mocha: {
                opts: './config/mocha.opts'
            }
        },
        reporters: [
            'progress',
            'coverage'
        ],
        coverageReporter: {
            type : 'html',
            dir : 'coverage/',
            subdir: browser => {
                // normalization process to keep a consistent browser name across different
                // https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md#subdir
                return browser.toLowerCase().split(/[ /-]/)[0];
            }
        }
    });
};<commit_msg>removed not available mocha opts<commit_after>// karma.conf.js
module.exports = config => {
    config.set({
        basePath: '../',
        preprocessors: {
            'src/**/*.js': ['babel'],
            '**/src/**/*.js': ['coverage']
        },
        babelPreprocessor: {
            options: {
                presets: ['es2015'],
                sourceMap: 'inline'
            },
            filename: file => {
                return file.originalPath.replace(/\.js$/, '.es5.js');
            },
            sourceFileName: file => {
                return file.originalPath;
            }
        },
        files: [
            'dev/assets/js/vendor.js',
            'src/**/*.js',
            'src/**/*.spec.js'
        ],
        browsers: [
            'PhantomJS',
            'Firefox',
            'Chrome'
        ],
        frameworks: [
            'mocha',
            'chai'
        ],
        autoWatch: false,
        reporters: [
            'progress',
            'coverage'
        ],
        coverageReporter: {
            type : 'html',
            dir : 'coverage/',
            subdir: browser => {
                // normalization process to keep a consistent browser name across different
                // https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md#subdir
                return browser.toLowerCase().split(/[ /-]/)[0];
            }
        }
    });
};<|endoftext|>


<commit_before> module.exports = function(app) {

    var multer = require('multer');
    var fs = require('fs');
    var XLSX = require("xlsx");
    var jsonfile = require('jsonfile');
    var parse = require('../scripts/parseExcel.js');
    var convertWB = require('../scripts/parseWorkbook.js');
    var Config = require('../model/configuration');
    var Imagemap = require('../model/imagemap');
    var Timeline = require('../model/timeline');

    var storage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '/tmp/uploads/')
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname);
        }
    });

    var upload = multer({ //multer settings
        storage: storage,
        fileFilter : function(req, file, callback) { //file filter
            if (['xlsx'].indexOf(file.originalname.split('.')[file.originalname.split('.').length-1]) === -1) {
                return callback(new Error('Wrong extension. Please upload an xlsx file.'));
            }
            callback(null, true);
        }
    }).single('file');

    var imagestorage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '/tmp/uploads/');
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname);
        }
    });

    var imageupload = multer({ //multer settings to upload image and its contents
        storage: imagestorage,
        fileFilter : function(req, file, callback) { //file filter
            if(file.fieldname === 'image'){
                if (file.mimetype !== 'image/jpeg') {
                    console.log('Wrong format!');
                    return callback(null, false, new Error('Wrong format!'));
                }
            }
            callback(null, true);

        }
    }).fields([{
        name: 'image', maxCount: 1
    }, {
        name: 'contents', maxCount: 1
    }]);

    var filestorage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '/tmp/uploads/')
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname);
        }
    });

    var timelinedataupload = multer({ //multer settings
        storage: filestorage,
        fileFilter : function(req, file, callback) { //file filter
            if (['xlsx'].indexOf(file.originalname.split('.')[file.originalname.split('.').length-1]) === -1) {
                return callback(new Error('Wrong extension. Please upload an xlsx file.'));
            }
            callback(null, true);
        }
    }).single('file');

    app.get('/',function(req,res){
        res.render("index");
    });

    app.get('/sources', function(req,res){
        res.render("sources");
    });

    app.get('/imageuploads', function(req,res){
        res.render("imageuploads");
    });

    app.get('/timelineuploads', function(req,res){
        res.render("timelineuploads");
    });

    app.get('/navbar',function(req,res){
        res.render("navbar");
    });

    app.get('/help',function(req,res){
        res.render("help");
    });

    app.get('/getConfig', function(req,res){
        Config.find({}, { source : 1, mission : 1 }, function(err, config) {
            if (err) {
                console.log("Error finding configurations in DB: " + err);
                throw err;
            }

            res.send(config);
        });
    });

    //Displays all the images of each mission in display sources page in a table
    app.get('/getImageList', function(req,res){
        Imagemap.find({}, {}, function(err, mapdata) {
            if (err) {
                console.log("Error finding map data in DB: " + err);
                throw err;
            }

            var imagelist = [];
            for(var i=0;i<mapdata.length;i++){
                for(j=0;j<mapdata[i].uploadedfiles.length;j++){
                    imagelist.push({
                        "imageid":mapdata[i].uploadedfiles[j].imageid,
                        "mission":mapdata[i].mission,
                        "imagefile":mapdata[i].uploadedfiles[j].imagefile,
                        "contentsfile":mapdata[i].uploadedfiles[j].contentsfile
                    });
                }
            }
           res.send(imagelist);
        });
    });

    app.post('/upload', function(req, res) {
        upload(req,res,function(err){
            if(err){
                res.json({error_code:1,err_desc:err});
                return;
            }

            parse(req,res);
            res.json({error_code:0,err_desc:null});
        });
    });

    //To save image and its valid contents
    app.post('/saveImages', function(req, res) {
        imageupload(req,res,function(err){
            if(err){
                console.log(err);
                res.json({error_code:1,err_desc:err});
                return;
            }

            var contents = jsonfile.readFileSync(req.files.contents[0].path);
            var img = fs.readFileSync(req.files.image[0].path);
            var imgfile = req.files.image[0].originalname;
            var contsfile = req.files.contents[0].originalname;
            for(var i=0;i<contents.length;i++){
                if(contents[i].id === "" || contents[i].coords === {} || contents[i].coords.position === "" || contents[i].coords.top === "" || contents[i].coords.left === ""){
                    res.json({error_code:1,err_desc:"bad json"});
                    return;
                }
            }

            Imagemap.findOne({'mission' : req.body.mission }, function(err, docmaps) {
                if(err){
                    console.log(err);
                }

                if(docmaps){
                    docmaps.uploadedfiles.push({
                        "imageid" : req.body.imageid,
                        "image" : img,
                        "contents" : contents,
                        "imagefile" : imgfile,
                        "contentsfile" : contsfile
                    });

                    docmaps.markModified('uploadedfiles');
                    docmaps.save(function(err) {
                        if (err) throw err;
                        console.log(' image map data updated successfully for ' + req.body.mission);
                    });
                }else {
                    //create a new document if not document exists
                    var imaps = new Imagemap();
                    imaps.mission =  req.body.mission;
                    imaps.uploadedfiles.push({
                        "imageid" : req.body.imageid,
                        "image" : img,
                        "contents" : contents,
                        "imagefile" : imgfile,
                        "contentsfile" : contsfile
                    })

                    imaps.save(function(err,result){
                        if(err){
                            console.log(err);
                        }
                        if(result){
                            console.log('map data saved successfully for ' + req.body.mission);
                        }
                    });
                }
            });
            res.json({error_code:0,err_desc:null});
        });
    });

    app.post('/removeImageMap', function(req,res){
        var imageid = req.body.imageid;
        var mission = req.body.mission;
        Imagemap.findOne({'mission':mission}, function(err, mapdata) {
            if (err) {
                console.log("Error finding map data in DB: " + err);
                throw err;
            }
            if(mapdata){
                for(var i=0;i<mapdata.uploadedfiles.length;i++){
                    if(mapdata.uploadedfiles[i].imageid === imageid){
                        mapdata.uploadedfiles.splice(i,1);
                    }
                }

                mapdata.markModified('uploadedfiles');
                mapdata.save(function(err) {
                    if (err) throw err;
                    console.log(' The image map:' + imageid +' for ' +req.body.mission + 'is deleted.');
                });
            }
        });
        res.json({error_code:0,err_desc:null});
    });

    //To save Timeline Data
    app.post('/saveTimelineData', function(req, res) {
        timelinedataupload(req,res,function(err){
            if(err){
                console.log(err);
                res.json({error_code:1,err_desc:err});
                return;
            }

            try {
                var filepath = req.file.path;
                var workbook = XLSX.readFile(filepath);
                var sheet1 = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet1);
                var sheet2 = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet2);
                var newgroupContents = [];
                var d1,d2,timerange;
                var sheets = {
                    "sheet1":sheet1,
                    "sheet2":sheet2,
                    "workbook":workbook
                }

                for(var i=0;i<sheet1.length;i++){
                    newgroupContents.push({"eventname":sheet1[i].eventname,"eventdata":[],"eventgroup":sheet1[i].eventgroup,"eventinfo":sheet1[i].eventinfo});
                }

                for(var j=0;j<sheet1.length;j++){
                    for(var k=0;k<sheet2.length;k++){
                        for(var l=0;l<Object.keys(sheet2[k]).length;l++){
                            if(newgroupContents[j].eventname === Object.keys(sheet2[k])[l]){
                                if(sheet2[k][Object.keys(sheet2[k])[l]] !== "{}"){
                                    d1 =  sheet2[k][Object.keys(sheet2[k])[l]].replace("{", "");
                                    d2 =  d1.replace("}","");
                                    timerange = d2.split(",");
                                    newgroupContents[j].eventdata.push({
                                        "start":timerange[0],
                                        "end":timerange[1],
                                        "content":timerange[2]
                                    });
                                }else {
                                    newgroupContents[j].eventdata.push({
                                        "start":"",
                                        "end":"",
                                        "content":""
                                    });
                                }
                            }
                        }
                    }
                }

                Timeline.findOne({'mission' : req.body.mission }, function(err, docmaps) {
                    if(err){
                        console.log(err);
                    }

                    if(docmaps){
                        docmaps.events = newgroupContents;
                        docmaps.filename = req.body.filename;
                        docmaps.file = req.file.originalname;
                        docmaps.markModified('file');
                        docmaps.markModified('filename');
                        docmaps.markModified('events');
                        docmaps.save(function(err) {
                        if (err) throw err;
                            console.log(' Timeline data updated successfully for ' + req.body.mission);
                        });
                    }else {
                        //create a new document if not document exists
                        var timeline = new Timeline();
                        timeline.mission =  req.body.mission;
                        timeline.filename = req.body.filename;
                        timeline.file = req.file.originalname;
                        for(var i=0;i<newgroupContents.length;i++){
                            timeline.events.push(newgroupContents[i]);
                        }
                        timeline.save(function(err,result){
                            if(err){
                                console.log(err);
                            }
                            if(result){
                                console.log('Timeline data saved successfully for ' + req.body.mission);
                            }
                        });
                    }
                });

                if(sheets.sheet1.length > 0 && sheets.sheet2.length > 0){
                    res.json({error_code:0,err_desc:null});
                }else {
                    res.json({error_code:1,err_desc:"No excel data"});
                }

            } catch (e){
                res.json({error_code:1,err_desc:"Corupted excel file"});
            }
        });
    });

    //Displays all the timeline files of each mission in a table
    app.get('/getMissionTimelines', function(req,res){
        Timeline.find({}, {}, function(err, timelinedata) {
            if (err) {
                console.log("Error finding map data in DB: " + err);
                throw err;
            }

            var timelinelist = [];
            for(var i=0;i<timelinedata.length;i++){
                    timelinelist.push({
                        "filename":timelinedata[i].filename,
                        "mission":timelinedata[i].mission,
                        "file":timelinedata[i].file
                    });
            }
           res.send(timelinelist);
        });
    });
}<commit_msg>commiting routes file<commit_after> module.exports = function(app) {

    var multer = require('multer');
    var fs = require('fs');
    var XLSX = require("xlsx");
    var jsonfile = require('jsonfile');
    var parse = require('../scripts/parseExcel.js');
    var Config = require('../model/configuration');
    var Imagemap = require('../model/imagemap');
    var Timeline = require('../model/timeline');

    var storage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '/tmp/uploads/')
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname);
        }
    });

    var upload = multer({ //multer settings
        storage: storage,
        fileFilter : function(req, file, callback) { //file filter
            if (['xlsx'].indexOf(file.originalname.split('.')[file.originalname.split('.').length-1]) === -1) {
                return callback(new Error('Wrong extension. Please upload an xlsx file.'));
            }
            callback(null, true);
        }
    }).single('file');

    var imagestorage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '/tmp/uploads/');
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname);
        }
    });

    var imageupload = multer({ //multer settings to upload image and its contents
        storage: imagestorage,
        fileFilter : function(req, file, callback) { //file filter
            if(file.fieldname === 'image'){
                if (file.mimetype !== 'image/jpeg') {
                    console.log('Wrong format!');
                    return callback(null, false, new Error('Wrong format!'));
                }
            }
            callback(null, true);

        }
    }).fields([{
        name: 'image', maxCount: 1
    }, {
        name: 'contents', maxCount: 1
    }]);

    var filestorage = multer.diskStorage({ //multers disk storage settings
        destination: function (req, file, cb) {
            cb(null, '/tmp/uploads/')
        },
        filename: function (req, file, cb) {
            cb(null, file.originalname);
        }
    });

    var timelinedataupload = multer({ //multer settings
        storage: filestorage,
        fileFilter : function(req, file, callback) { //file filter
            if (['xlsx'].indexOf(file.originalname.split('.')[file.originalname.split('.').length-1]) === -1) {
                return callback(new Error('Wrong extension. Please upload an xlsx file.'));
            }
            callback(null, true);
        }
    }).single('file');

    app.get('/',function(req,res){
        res.render("index");
    });

    app.get('/sources', function(req,res){
        res.render("sources");
    });

    app.get('/imageuploads', function(req,res){
        res.render("imageuploads");
    });

    app.get('/timelineuploads', function(req,res){
        res.render("timelineuploads");
    });

    app.get('/navbar',function(req,res){
        res.render("navbar");
    });

    app.get('/help',function(req,res){
        res.render("help");
    });

    app.get('/getConfig', function(req,res){
        Config.find({}, { source : 1, mission : 1 }, function(err, config) {
            if (err) {
                console.log("Error finding configurations in DB: " + err);
                throw err;
            }

            res.send(config);
        });
    });

    //Displays all the images of each mission in display sources page in a table
    app.get('/getImageList', function(req,res){
        Imagemap.find({}, {}, function(err, mapdata) {
            if (err) {
                console.log("Error finding map data in DB: " + err);
                throw err;
            }

            var imagelist = [];
            for(var i=0;i<mapdata.length;i++){
                for(j=0;j<mapdata[i].uploadedfiles.length;j++){
                    imagelist.push({
                        "imageid":mapdata[i].uploadedfiles[j].imageid,
                        "mission":mapdata[i].mission,
                        "imagefile":mapdata[i].uploadedfiles[j].imagefile,
                        "contentsfile":mapdata[i].uploadedfiles[j].contentsfile
                    });
                }
            }
           res.send(imagelist);
        });
    });

    app.post('/upload', function(req, res) {
        upload(req,res,function(err){
            if(err){
                res.json({error_code:1,err_desc:err});
                return;
            }

            parse(req,res);
            res.json({error_code:0,err_desc:null});
        });
    });

    //To save image and its valid contents
    app.post('/saveImages', function(req, res) {
        imageupload(req,res,function(err){
            if(err){
                console.log(err);
                res.json({error_code:1,err_desc:err});
                return;
            }

            var contents = jsonfile.readFileSync(req.files.contents[0].path);
            var img = fs.readFileSync(req.files.image[0].path);
            var imgfile = req.files.image[0].originalname;
            var contsfile = req.files.contents[0].originalname;
            for(var i=0;i<contents.length;i++){
                if(contents[i].id === "" || contents[i].coords === {} || contents[i].coords.position === "" || contents[i].coords.top === "" || contents[i].coords.left === ""){
                    res.json({error_code:1,err_desc:"bad json"});
                    return;
                }
            }

            Imagemap.findOne({'mission' : req.body.mission }, function(err, docmaps) {
                if(err){
                    console.log(err);
                }

                if(docmaps){
                    docmaps.uploadedfiles.push({
                        "imageid" : req.body.imageid,
                        "image" : img,
                        "contents" : contents,
                        "imagefile" : imgfile,
                        "contentsfile" : contsfile
                    });

                    docmaps.markModified('uploadedfiles');
                    docmaps.save(function(err) {
                        if (err) throw err;
                        console.log(' image map data updated successfully for ' + req.body.mission);
                    });
                }else {
                    //create a new document if not document exists
                    var imaps = new Imagemap();
                    imaps.mission =  req.body.mission;
                    imaps.uploadedfiles.push({
                        "imageid" : req.body.imageid,
                        "image" : img,
                        "contents" : contents,
                        "imagefile" : imgfile,
                        "contentsfile" : contsfile
                    })

                    imaps.save(function(err,result){
                        if(err){
                            console.log(err);
                        }
                        if(result){
                            console.log('map data saved successfully for ' + req.body.mission);
                        }
                    });
                }
            });
            res.json({error_code:0,err_desc:null});
        });
    });

    app.post('/removeImageMap', function(req,res){
        var imageid = req.body.imageid;
        var mission = req.body.mission;
        Imagemap.findOne({'mission':mission}, function(err, mapdata) {
            if (err) {
                console.log("Error finding map data in DB: " + err);
                throw err;
            }
            if(mapdata){
                for(var i=0;i<mapdata.uploadedfiles.length;i++){
                    if(mapdata.uploadedfiles[i].imageid === imageid){
                        mapdata.uploadedfiles.splice(i,1);
                    }
                }

                mapdata.markModified('uploadedfiles');
                mapdata.save(function(err) {
                    if (err) throw err;
                    console.log(' The image map:' + imageid +' for ' +req.body.mission + 'is deleted.');
                });
            }
        });
        res.json({error_code:0,err_desc:null});
    });

    //To save Timeline Data
    app.post('/saveTimelineData', function(req, res) {
        timelinedataupload(req,res,function(err){
            if(err){
                console.log(err);
                res.json({error_code:1,err_desc:err});
                return;
            }

            try {
                var filepath = req.file.path;
                var workbook = XLSX.readFile(filepath);
                var sheet1 = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet1);
                var sheet2 = XLSX.utils.sheet_to_json(workbook.Sheets.Sheet2);
                var newgroupContents = [];
                var d1,d2,timerange;
                var sheets = {
                    "sheet1":sheet1,
                    "sheet2":sheet2,
                    "workbook":workbook
                }

                for(var i=0;i<sheet1.length;i++){
                    newgroupContents.push({"eventname":sheet1[i].eventname,"eventdata":[],"eventgroup":sheet1[i].eventgroup,"eventinfo":sheet1[i].eventinfo});
                }

                for(var j=0;j<sheet1.length;j++){
                    for(var k=0;k<sheet2.length;k++){
                        for(var l=0;l<Object.keys(sheet2[k]).length;l++){
                            if(newgroupContents[j].eventname === Object.keys(sheet2[k])[l]){
                                if(sheet2[k][Object.keys(sheet2[k])[l]] !== "{}"){
                                    d1 =  sheet2[k][Object.keys(sheet2[k])[l]].replace("{", "");
                                    d2 =  d1.replace("}","");
                                    timerange = d2.split(",");
                                    newgroupContents[j].eventdata.push({
                                        "start":timerange[0],
                                        "end":timerange[1],
                                        "content":timerange[2]
                                    });
                                }else {
                                    newgroupContents[j].eventdata.push({
                                        "start":"",
                                        "end":"",
                                        "content":""
                                    });
                                }
                            }
                        }
                    }
                }

                Timeline.findOne({'mission' : req.body.mission }, function(err, docmaps) {
                    if(err){
                        console.log(err);
                    }

                    if(docmaps){
                        docmaps.events = newgroupContents;
                        docmaps.filename = req.body.filename;
                        docmaps.file = req.file.originalname;
                        docmaps.markModified('file');
                        docmaps.markModified('filename');
                        docmaps.markModified('events');
                        docmaps.save(function(err) {
                        if (err) throw err;
                            console.log(' Timeline data updated successfully for ' + req.body.mission);
                        });
                    }else {
                        //create a new document if not document exists
                        var timeline = new Timeline();
                        timeline.mission =  req.body.mission;
                        timeline.filename = req.body.filename;
                        timeline.file = req.file.originalname;
                        for(var i=0;i<newgroupContents.length;i++){
                            timeline.events.push(newgroupContents[i]);
                        }
                        timeline.save(function(err,result){
                            if(err){
                                console.log(err);
                            }
                            if(result){
                                console.log('Timeline data saved successfully for ' + req.body.mission);
                            }
                        });
                    }
                });

                if(sheets.sheet1.length > 0 && sheets.sheet2.length > 0){
                    res.json({error_code:0,err_desc:null});
                }else {
                    res.json({error_code:1,err_desc:"No excel data"});
                }

            } catch (e){
                res.json({error_code:1,err_desc:"Corupted excel file"});
            }
        });
    });

    //Displays all the timeline files of each mission in a table
    app.get('/getMissionTimelines', function(req,res){
        Timeline.find({}, {}, function(err, timelinedata) {
            if (err) {
                console.log("Error finding map data in DB: " + err);
                throw err;
            }

            var timelinelist = [];
            for(var i=0;i<timelinedata.length;i++){
                    timelinelist.push({
                        "filename":timelinedata[i].filename,
                        "mission":timelinedata[i].mission,
                        "file":timelinedata[i].file
                    });
            }
           res.send(timelinelist);
        });
    });
}<|endoftext|>