<commit_before>(function() {
    function SongPlayer() {
        var SongPlayer = {};

        var currentSong = null;

        /**
         * @desc Buzz object audio file
         * @type {Object}
         */
        var currentBuzzObject = null;

        /**
         * @function setSong
         * @desc Stops currently playing song and loads new audio file as currentBuzzObject
         * @param {Object} song
         */
        var setSong = function(song) {
            if (currentBuzzObject) {
                currentBuzzObject.stop();
                currentSong.playing = null;
            }

            currentBuzzObject = new buzz.sound(song.audioUrl, {
                formats: ['mp3'],
                preload: true
            });

            currentSong = song;
        };

        SongPlayer.play = function(song) {
            if (currentSong !== song) {
                setSong(song);
                song.playing = true;
                currentBuzzObject.play();

            } else if (currentSong === song) {
                if (currentBuzzObject.isPaused()) {
                    currentBuzzObject.play();
                    song.playing = true;
                }
            }
        };

        SongPlayer.pause = function(song) {
            currentBuzzObject.pause();
            song.playing = false;
        };

        return SongPlayer;
    }

    angular
        .module('blocJams')
        .factory('SongPlayer', SongPlayer);
})();<commit_msg>Assignment 7: Services part two. Added extra notation to all of the variables and methods of the SongPlayer Service.<commit_after>(function() {
    function SongPlayer() {
        /**
         * @desc Creates the actual SongPlayer Object to attach the subsequent methods
         * @type {Object}
         */
        var SongPlayer = {};

        /**
         * @desc Current song object
         * @type {Object}
         */
        var currentSong = null;

        /**
         * @desc Buzz object audio file
         * @type {Object}
         */
        var currentBuzzObject = null;

        /**
         * @function PlaySong
         * @desc Plays the current Buzz object and sets the playing attribute to true
         * @param {Object} song
         */
        var playSong = function(song) {
            song.playing = true;
            currentBuzzObject.play();
        };

        /**
         * @function setSong
         * @desc Stops currently playing song and loads new audio file as currentBuzzObject
         * @param {Object} song
         */
        var setSong = function(song) {
            if (currentBuzzObject) {
                currentBuzzObject.stop();
                currentSong.playing = null;
            }

            currentBuzzObject = new buzz.sound(song.audioUrl, {
                formats: ['mp3'],
                preload: true
            });

            currentSong = song;
        };

        /**
         * @function play
         * @desc Play logic for the song player
         * @param {Object} song
         */
        SongPlayer.play = function(song) {
            if (currentSong !== song) {
                setSong(song);
                playSong(song);

            } else if (currentSong === song) {
                if (currentBuzzObject.isPaused()) {
                    playSong(song);
                }
            }
        };

        /**
         * @function pause
         * @desc Pause logic for the song player
         * @param {Object} song
         */
        SongPlayer.pause = function(song) {
            currentBuzzObject.pause();
            song.playing = false;
        };

        return SongPlayer;
    }

    angular
        .module('blocJams')
        .factory('SongPlayer', SongPlayer);
})();<|endoftext|>


<commit_before>'use strict';

var request = require('request');

var path = process.cwd();
var SearchEvent = require(path + '/app/models/SearchEvent.js');

function ImageSearchService() {

    this.searchQuery = function (req, res) {

        var query = req.params.query;
        var cx = process.env.GOOGLE_CX;
        var key = process.env.GOOGLE_API_KEY;

        var options = {
            host: 'googleapis.com',
            port: 443,
            method: 'GET',
            path: '/customsearch/v1?searchType=image&cx=' + cx + '&key=' + key + '&q=' + query
        };

        console.log(JSON.stringify(options));

        var qs = {
            cx: cx,
            key: key,
            q: query
        };
        var name = {url: 'https://www.googleapis.com:443/customsearch/v1', qs: qs, json: true};
        request.get(name, function (e, r) {
            console.log('e:' + JSON.stringify(e));
            console.log('r:' + JSON.stringify(r));

            var images = [];
            var items = r.body.items;
            if(items) {
                images = items.map(function(e) {
                    console.log(JSON.stringify(e));
                    var thumbnail = e.pagemap.cse_thumbnail;
                    if (!thumbnail) {
                        thumbnail = e.pagemap.imageobject.url;
                    }
                   return {
                       url: e.url,
                       snippet: e.snippet,
                       thumbnail: thumbnail,
                       context: e.link
                   }
                });
            }

            return res.json(images);
        });

        var searchEvent = new SearchEvent({
            term: query,
            when: Date.now()
        });
        searchEvent.save(function (err, searchEvent) {
            if (err) {
                console.log(err + ', searchEvent:' + JSON.stringify(searchEvent));
            }
        });
    };

    this.searchHistory =  function(req, res) {
        var query = SearchEvent.find().limit(20);
        query.exec(function(err, searchEvents) {
            if (err) {
                return res.json(500, {
                    message: 'Error',
                    error: err
                });
            }
            var filteredSearchEvents = searchEvents.map(function(e) {
                return {term: e.term, when: e.when};
            });
            return res.json(filteredSearchEvents);
        });
    };
}

module.exports = ImageSearchService;<commit_msg>- Removed unused code - Added offset parameter to requests<commit_after>'use strict';

var request = require('request');

var path = process.cwd();
var SearchEvent = require(path + '/app/models/SearchEvent.js');

function ImageSearchService() {

    this.searchQuery = function (req, res) {

        var query = req.params.query;
        var cx = process.env.GOOGLE_CX;
        var key = process.env.GOOGLE_API_KEY;

        var offset = req.query.offset;
        var resultsPerPage = 10;

        var qs = {
            cx: cx,
            key: key,
            q: query,
            num: resultsPerPage
        };
        if (offset && offset > 0) {
            qs.start = offset*resultsPerPage + 1;
        }
        console.log('###:' + JSON.stringify(qs));

        var name = {url: 'https://www.googleapis.com:443/customsearch/v1', qs: qs, json: true};
        request.get(name, function (e, r) {
            console.log('e:' + JSON.stringify(e));
            console.log('r:' + JSON.stringify(r));

            var images = [];
            var items = r.body.items;
            if(items) {
                images = items.map(function(e) {
                    console.log(JSON.stringify(e));
                    var thumbnail = e.pagemap.cse_thumbnail;
                    if (!thumbnail) {
                        thumbnail = e.pagemap.imageobject.url;
                    }
                   return {
                       url: e.url,
                       snippet: e.snippet,
                       thumbnail: thumbnail,
                       context: e.link
                   }
                });
            }

            return res.json(images);
        });

        var searchEvent = new SearchEvent({
            term: query,
            when: Date.now()
        });
        searchEvent.save(function (err, searchEvent) {
            if (err) {
                console.log(err + ', searchEvent:' + JSON.stringify(searchEvent));
            }
        });
    };

    this.searchHistory =  function(req, res) {
        var query = SearchEvent.find().limit(20);
        query.exec(function(err, searchEvents) {
            if (err) {
                return res.json(500, {
                    message: 'Error',
                    error: err
                });
            }
            var filteredSearchEvents = searchEvents.map(function(e) {
                return {term: e.term, when: e.when};
            });
            return res.json(filteredSearchEvents);
        });
    };
}

module.exports = ImageSearchService;<|endoftext|>


<commit_before>import Settings from 'utils/Settings';

import cs from './lang/cs';
import en from './lang/en';
import es from './lang/es';
import nl from './lang/nl';
import sk from './lang/sk';

const ALL = [
  cs,
  en,
  es,
  nl,
  sk
];

function getAvailable() {
  return ALL.slice();
}

function getSelected() {
  return Settings.get().then(({ language }) => language);
}

function find(languageCode) {
  const majorLanguageCode = languageCode.split(/-_/).shift().toLowerCase();

  return ALL.find(({ code }) => code === majorLanguageCode);
}

function detect(document) {
  const siteLanguageCode = document.documentElement.getAttribute('lang');
  const navigatorLanguageCode = navigator.language;
  const detectedlanguage = find(siteLanguageCode) || find(navigatorLanguageCode);

  return detectedlanguage || null;
}

export default {
  detect,
  find,
  getAvailable,
  getSelected
};
<commit_msg>Default to english if no better options available<commit_after>import Settings from 'utils/Settings';

import cs from './lang/cs';
import en from './lang/en';
import es from './lang/es';
import nl from './lang/nl';
import sk from './lang/sk';

const ALL = [
  cs,
  en,
  es,
  nl,
  sk
];

function getAvailable() {
  return ALL.slice();
}

function getSelected() {
  return Settings.get().then(({ language }) => language);
}

function find(languageCode) {
  const majorLanguageCode = languageCode.split(/-_/).shift().toLowerCase();

  return ALL.find(({ code }) => code === majorLanguageCode);
}

function detect(document) {
  const siteLanguageCode = document.documentElement.getAttribute('lang');
  const navigatorLanguageCode = navigator.language;
  const detectedlanguage = find(siteLanguageCode) || find(navigatorLanguageCode) || find('en');

  return detectedlanguage || null;
}

export default {
  detect,
  find,
  getAvailable,
  getSelected
};
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
    View,
    Platform,
    Dimensions,
    PixelRatio
} from 'react-native';
import Mapbox, { MapView } from 'react-native-mapbox-gl';
import { connect } from 'react-redux';
import store from 'react-native-simple-store';
import Config from '../../constants/Config';
import { showMapModeFullscreen } from '../../actions/MapActions';
import { downloadMissions, startMission } from '../../actions/MissionActions';
import { downloadAchievements } from '../../actions/AchievementsActions';
import GeoLocation from '../../geolocation/GeoLocation';
import { RoundButton } from '../common';
import { SETTINGS } from '../../storage/StorageKeys';

class Map extends Component {

    state = { firstTapAt: 0, annotationOpen: false, annotationOpenedAt: 0, regionChange: false, mapRotation: false };

    componentDidMount() {
        console.log(Config.MAPBOX_ACCESS_TOKEN);
        Mapbox.setAccessToken(Config.MAPBOX_ACCESS_TOKEN);

        //TODO move this to other area
        this.props.downloadMissions();

        store.get(SETTINGS).then(settings => {
            if (settings !== null) {
                this.setState(settings);
                Mapbox.setMetricsEnabled(settings.stats);
            } else {
                Mapbox.setMetricsEnabled(false);
            }
        });
    }

    componentWillReceiveProps(nextProps) {
        let lastLocation = '';
        if (this.props && this.props.currentLocation) {
            lastLocation = this.props.currentLocation;
        }

        if (nextProps.currentLocation && (lastLocation !== nextProps.currentLocation)) {
            console.log(nextProps.currentLocation.coords);
            this.centerMapAroundLocation(nextProps.currentLocation.coords);
        }
    }

    onTap() {
        console.log('tap');
        const d = new Date();
        const now = d.getTime();
        if (now - this.state.firstTapAt > 500) {
            setTimeout(() => {
                this.toggleFullscreen();
            }, 500);
        }
        this.props.onTap();
        this.setState({ firstTapAt: d.getTime(), annotationOpen: false, activeMission: {} });
    }

    onRegionDidChange() {
        console.log('region changed');
        if (this.state.annotationOpen) {
            this.setState({ regionChange: true });
            this.map.selectAnnotation(this.props.activeMission.id);
        }
    }

    onOpenAnnotation(annotation) {
        const d = new Date();
        this.setState({ annotationOpenedAt: d.getTime() });

        if (this.state.currentMission !== annotation.id) {
            this.handleAnnotationOpen(annotation);
        } else {
            if (!this.state.regionChange && !this.state.annotationOpen) {
                this.handleAnnotationOpen(annotation);
            }
            this.setState({ regionChange: false });
        }
    }

    toggleFullscreen() {
        const d = new Date();
        const now = d.getTime();
        // 500ms between taps for not zooming, 500ms for not toggling when clicking on annotation
        if (now - this.state.firstTapAt > 500 && now - this.state.annotationOpenedAt > 500) {
            this.props.showMapModeFullscreen(!this.props.mapModeFullScreen);
        }
    }

    handleAnnotationOpen(annotation) {
        this.setState({ currentMission: annotation.id, annotationOpen: true });
            this.props.startMission(annotation.id);
            this.props.showMapModeFullscreen(true);
            this.props.onOpenAnnotation();

            //check if mission behind mission panel below center
            //TOOD handle rotation
            this.map.getCenterCoordinateZoomLevel(data => {
                this.map.getDirection(direction => {
                    if (annotation.latitude < data.latitude && direction === 0) {
                        this.map.setCenterCoordinate(annotation.latitude, annotation.longitude, true, null);
                    }
                });
            });
    }

    centerMapAroundCurrentLocation() {
        this.centerMapAroundLocation(this.props.currentLocation.coords);
    }

    centerMapAroundLocation(coords) {
        if (coords) {
            const { latitude, longitude } = coords;
            this.map.getCenterCoordinateZoomLevel(data => {
                const initialZoom = Config.MAPBOX_INITIAL_ZOOM_LEVEL;
                const zoom = initialZoom > data.zoomLevel ? initialZoom : data.zoomLevel;
                this.map.setCenterCoordinateZoomLevel(latitude, longitude,
                zoom, true, null);
            });
        }
    }

    map = null;

    render() {
        const { bgColor, mapStyleFullScreen, mapStyleSmallScreen,
            locBtnFullScreen, locBtnSmallScreen } = styles;
        return (
            <View style={bgColor}>
                <GeoLocation />
                <MapView
                    ref={map => { this.map = map; }}
                    style={this.props.mapModeFullScreen ? mapStyleFullScreen : mapStyleSmallScreen}
                    logoIsHidden
                    showsUserLocation
                    initialZoomLevel={13}
                    initialCenterCoordinate={{
                        latitude: Config.MAPBOX_INITIAL_COORD_LATITUDE,
                        longitude: Config.MAPBOX_INITIAL_COORD_LONGITUDE
                    }}
                    onOpenAnnotation={this.onOpenAnnotation.bind(this)}
                    onRegionDidChange={this.onRegionDidChange.bind(this)}
                    onTap={this.onTap.bind(this)}
                    annotations={this.props.missionAnnotations}
                    styleURL={styleURL}
                    attributionButtonIsHidden
                    rotateEnabled={this.state.mapRotation}
                />
                <RoundButton
                    style={this.props.mapModeFullScreen ? locBtnFullScreen : locBtnSmallScreen}
                    iconName='my-location'
                    onPress={this.centerMapAroundCurrentLocation.bind(this)}
                />
            </View>
        );
    }
}

const styleURL = Config.MAPBOX_STYLE_URL ? Config.MAPBOX_STYLE_URL : Mapbox.mapStyles.streets;

const deviceWidth = Dimensions.get('window').width * PixelRatio.get();

const styles = {
    bgColor: {
        backgroundColor: '#395971',
        flex: 1,
    },
    mapStyleFullScreen: {
        flex: 1,
        marginTop: 0,
        marginBottom: 0
    },
    mapStyleSmallScreen: {
        flex: 1,
        marginTop: (Platform.OS === 'ios') ? 64 : 54,
        marginBottom: 50
    },
    locBtnFullScreen: {
        position: 'absolute',
        right: (Platform.OS === 'ios') ? 5 : 13,
        marginTop: (Platform.OS === 'ios') ? 51 : 72,
    },
    locBtnSmallScreen: {
        position: 'absolute',
        right: (Platform.OS === 'ios') ? 5 : 13,
        marginTop: (Platform.OS === 'ios') ? 115 : 126,
    }

};

const mapStateToProps = ({ mapReducer, missionReducer }) => {
    console.log(missionReducer);
    const { mapModeFullScreen, currentLocation } = mapReducer;
    const { missionAnnotations, activeMission } = missionReducer;
    return { mapModeFullScreen, currentLocation, missionAnnotations, activeMission };
};

export default connect(mapStateToProps,
    { showMapModeFullscreen, downloadMissions, startMission, downloadAchievements })(Map);
<commit_msg>fix fullscreen mode fail on android<commit_after>import React, { Component } from 'react';
import {
    View,
    Platform,
    Dimensions,
    PixelRatio
} from 'react-native';
import Mapbox, { MapView } from 'react-native-mapbox-gl';
import { connect } from 'react-redux';
import store from 'react-native-simple-store';
import Config from '../../constants/Config';
import { showMapModeFullscreen } from '../../actions/MapActions';
import { downloadMissions, startMission } from '../../actions/MissionActions';
import { downloadAchievements } from '../../actions/AchievementsActions';
import GeoLocation from '../../geolocation/GeoLocation';
import { RoundButton } from '../common';
import { SETTINGS } from '../../storage/StorageKeys';

class Map extends Component {

    state = { firstTapAt: 0, annotationOpen: false, annotationOpenedAt: 0, regionChange: false, mapRotation: false };

    componentDidMount() {
        console.log(Config.MAPBOX_ACCESS_TOKEN);
        Mapbox.setAccessToken(Config.MAPBOX_ACCESS_TOKEN);

        //TODO move this to other area
        this.props.downloadMissions();

        store.get(SETTINGS).then(settings => {
            if (settings !== null) {
                this.setState(settings);
                Mapbox.setMetricsEnabled(settings.stats);
            } else {
                Mapbox.setMetricsEnabled(false);
            }
        });
    }

    componentWillReceiveProps(nextProps) {
        let lastLocation = '';
        if (this.props && this.props.currentLocation) {
            lastLocation = this.props.currentLocation;
        }

        if (nextProps.currentLocation && (lastLocation !== nextProps.currentLocation)) {
            console.log(nextProps.currentLocation.coords);
            this.centerMapAroundLocation(nextProps.currentLocation.coords);
        }
    }

    onTap() {
        console.log('tap');
        const d = new Date();
        const now = d.getTime();
        console.log(now - this.state.firstTapAt);
        if (now - this.state.firstTapAt > 500) {
            setTimeout(() => {
                this.toggleFullscreen();
            }, 500);
        }
        this.props.onTap();
        this.setState({ firstTapAt: d.getTime(), annotationOpen: false, activeMission: {} });
    }

    onRegionDidChange() {
        console.log('region changed');
        if (this.state.annotationOpen) {
            this.setState({ regionChange: true });
            this.map.selectAnnotation(this.props.activeMission.id);
        }
    }

    onOpenAnnotation(annotation) {
        const d = new Date();
        this.setState({ annotationOpenedAt: d.getTime() });

        if (this.state.currentMission !== annotation.id) {
            this.handleAnnotationOpen(annotation);
        } else {
            if (!this.state.regionChange && !this.state.annotationOpen) {
                this.handleAnnotationOpen(annotation);
            }
            this.setState({ regionChange: false });
        }
    }

    toggleFullscreen() {
        const d = new Date();
        const now = d.getTime();
        console.log('fullscreen', now - this.state.firstTapAt, now - this.state.annotationOpenedAt);
        // 500ms between taps for not zooming, 500ms for not toggling when clicking on annotation
        if (now - this.state.annotationOpenedAt > 500) {
            if (now - this.state.firstTapAt > 500 && Platform.OS === 'ios') {
                this.props.showMapModeFullscreen(!this.props.mapModeFullScreen);
            } else if (Platform.OS === 'android') {
                this.props.showMapModeFullscreen(!this.props.mapModeFullScreen);
            }
        }
    }

    handleAnnotationOpen(annotation) {
        this.setState({ currentMission: annotation.id, annotationOpen: true });
            this.props.startMission(annotation.id);
            this.props.showMapModeFullscreen(true);
            this.props.onOpenAnnotation();

            //check if mission behind mission panel below center
            //TOOD handle rotation
            this.map.getCenterCoordinateZoomLevel(data => {
                this.map.getDirection(direction => {
                    if (annotation.latitude < data.latitude && direction === 0) {
                        this.map.setCenterCoordinate(annotation.latitude, annotation.longitude, true, null);
                    }
                });
            });
    }

    centerMapAroundCurrentLocation() {
        this.centerMapAroundLocation(this.props.currentLocation.coords);
    }

    centerMapAroundLocation(coords) {
        if (coords) {
            const { latitude, longitude } = coords;
            this.map.getCenterCoordinateZoomLevel(data => {
                const initialZoom = Config.MAPBOX_INITIAL_ZOOM_LEVEL;
                const zoom = initialZoom > data.zoomLevel ? initialZoom : data.zoomLevel;
                this.map.setCenterCoordinateZoomLevel(latitude, longitude,
                zoom, true, null);
            });
        }
    }

    map = null;

    render() {
        const { bgColor, mapStyleFullScreen, mapStyleSmallScreen,
            locBtnFullScreen, locBtnSmallScreen } = styles;
        return (
            <View style={bgColor}>
                <GeoLocation />
                <MapView
                    ref={map => { this.map = map; }}
                    style={this.props.mapModeFullScreen ? mapStyleFullScreen : mapStyleSmallScreen}
                    logoIsHidden
                    showsUserLocation
                    initialZoomLevel={13}
                    initialCenterCoordinate={{
                        latitude: Config.MAPBOX_INITIAL_COORD_LATITUDE,
                        longitude: Config.MAPBOX_INITIAL_COORD_LONGITUDE
                    }}
                    onOpenAnnotation={this.onOpenAnnotation.bind(this)}
                    onRegionDidChange={this.onRegionDidChange.bind(this)}
                    onTap={this.onTap.bind(this)}
                    annotations={this.props.missionAnnotations}
                    styleURL={styleURL}
                    attributionButtonIsHidden
                    rotateEnabled={this.state.mapRotation}
                />
                <RoundButton
                    style={this.props.mapModeFullScreen ? locBtnFullScreen : locBtnSmallScreen}
                    iconName='my-location'
                    onPress={this.centerMapAroundCurrentLocation.bind(this)}
                />
            </View>
        );
    }
}

const styleURL = Config.MAPBOX_STYLE_URL ? Config.MAPBOX_STYLE_URL : Mapbox.mapStyles.streets;

const deviceWidth = Dimensions.get('window').width * PixelRatio.get();

const styles = {
    bgColor: {
        backgroundColor: '#395971',
        flex: 1,
    },
    mapStyleFullScreen: {
        flex: 1,
        marginTop: 0,
        marginBottom: 0
    },
    mapStyleSmallScreen: {
        flex: 1,
        marginTop: (Platform.OS === 'ios') ? 64 : 54,
        marginBottom: 50
    },
    locBtnFullScreen: {
        position: 'absolute',
        right: (Platform.OS === 'ios') ? 5 : 13,
        marginTop: (Platform.OS === 'ios') ? 51 : 72,
    },
    locBtnSmallScreen: {
        position: 'absolute',
        right: (Platform.OS === 'ios') ? 5 : 13,
        marginTop: (Platform.OS === 'ios') ? 115 : 126,
    }

};

const mapStateToProps = ({ mapReducer, missionReducer }) => {
    console.log(missionReducer);
    const { mapModeFullScreen, currentLocation } = mapReducer;
    const { missionAnnotations, activeMission } = missionReducer;
    return { mapModeFullScreen, currentLocation, missionAnnotations, activeMission };
};

export default connect(mapStateToProps,
    { showMapModeFullscreen, downloadMissions, startMission, downloadAchievements })(Map);
<|endoftext|>


<commit_before>

/** @return true if the device is iPad or iPad simulator
 */
function isPad() {
    return UIATarget.localTarget().model().indexOf("iPad")>=0;
}

var Direction = {
    Up    : {value:0, name:"Up"},
    Down  : {value:1, name:"Down"},
    Left  : {value:3, name:"Left"},
    Right : {value:4, name:"Right"}
};

var Check = "check";
var Tap = "tap";
var TryTap = "tryTap";
var Investigate = "investigate";
var Input = "input";
var Wait = "wait";
var Scroll = "scroll";
var Swipe = "swipe";
var TapPoint = "tapPoint";
var WaitFor = "waitFor";
var Pick = "pick";

var GlobalEnv = {
    // Configs
    // Users can set these values
    DefaultMaxWaitingTime : 10,
    EnableTableGroup : false,

    // Results
    // gsautomation.js should write to these variables
    ChildrenArrayCache : {},
    Pass : true,
};

/// Shortcut for debug log
function log(str) {
	UIALogger.logDebug(str);
}

/// short cut for getting main window
function win() {
	return UIATarget.localTarget().frontMostApp().mainWindow();
}

/// short cut for delay
function wait(i) {
	UIATarget.localTarget().delay(i);
}

/** Checks if 2 elements overlap
 */
function overlap(element1, element2) {
    var rect1 = element1.rect();
    var rect2 = element2.rect();
    return (rect1.origin.x + rect1.size.width > rect2.origin.x && rect2.origin.x + rect2.size.width > rect1.origin.x
            && rect1.origin.y + rect1.size.height > rect2.origin.y && rect2.origin.y + rect2.size.height > rect1.origin.y);
}

/** return the center point of a rect, a dict with x and y
 */
function centerPoint(r) {
    return {x: (r.origin.x+r.size.width/2), y: (r.origin.y+r.size.height/2)};
}

/** return the screen center point, a dict with x and y
 */
function screenCenter() {
    var size = win().rect().size;
    return {x: size.width/2, y: size.height/2};
}

/** check if an element is inside screen
 */
function inScreen(element) {
    if (!element || !(element instanceof UIAElement)) return false;
    var size = element.rect().size;
	return overlap(element, win()) && size.width>0 && size.height>0;
}

/** converts a rect object to a string
 */
function rect2str(r) {
    return "(" + r.origin.x + ", " + r.origin.y + ") w=" + r.size.width + ", h="+ r.size.height;
}

/** Get an array of children for an element.
 * if allowCache is true, it might return the result from last childrenArray call
 */
function childrenArray(element, allowCache) {
    var elementText = debugText(element);
    if (allowCache) {
        var cachedArray = GlobalEnv.ChildrenArrayCache[elementText];
        if (cachedArray) {
            return cachedArray;
        }
    }
    var children = (element instanceof UIATableView)? element.visibleCells() : element.elements();
    var array = children.toArray();
    if (GlobalEnv.EnableTableGroup && (element instanceof UIATableView)) {
        var groups = element.groups(); // this call takes 5 sec for tables without groups..
        if (groups) {
            array = array.concat(groups.toArray());
        }
    }
    if (!array) {
        array = []; // at least make it an object so we can cache
    }
    GlobalEnv.ChildrenArrayCache[elementText] = array;
    return array;
}

function bustChildArrayCache() {
    GlobalEnv.ChildrenArrayCache = {};
}

/** Get the debug text of an element
 */
function debugText(element) {
    var text = "[" + element.name() + "] " + element + " @ " + rect2str(element.rect());
    return text;
}

/** Mark the result as passed or failed in instruments
 */
function displayResult() {
    if (GlobalEnv.Pass) {
        UIALogger.logPass("Passed all tests");
    }
    else {
        UIALogger.logFail("Failed");
    }
}

/// Safer than built-in logElementTree since this doesn't do recursion
function logChildren(element) {
    var array = childrenArray(element, false);
    for (var i in array) {
        var element = array[i];
        var prefix = inScreen(element)? "√ " : "X "
        log( prefix + debugText(element) );
    }
}

/// Safer than built-in logElementTree since this does recursion more conservatively
function logTree(element) {
    var stack = [element];
    var levelStack = [0];
    bustChildArrayCache();
    while (stack.length) {
        var current = stack.pop();
        var currentLevel = levelStack.pop();
        log("* " + Array(currentLevel).join("- ") + debugText(current));
        var children = childrenArray(current, true);
        for (var i in children.reverse()) {
            var child = children[i];
            if (inScreen(child) && !(child instanceof UIAApplication) ) {
                var childLevel = currentLevel + 1;
                levelStack.push(childLevel)
                stack.push(child);
            }
        }
    }
}

/** Swipe at a point to a direction
 * point is a dictionary with keys: x and y
 * direction is an instance of Direction enum
 */
function swipe(point, direction, distance, duration) {

    if (!distance) {
        distance = isPad() ? 300 : 100;
    }

    var humanFingerChubbiness = 5;
    var to = {};
    to.x = point.x;
    to.y = point.y;
    if (direction == Direction.Up) {
        to.y = to.y - distance;
        to.x = to.x + humanFingerChubbiness;
    }
    else if (direction == Direction.Down) {
        to.y = to.y + distance;
        to.x = to.x + humanFingerChubbiness;
    }
    else if (direction == Direction.Left) {
        to.x = to.x - distance;
        to.y = to.y + humanFingerChubbiness;
    }
    else if (direction == Direction.Right) {
        to.x = to.x + distance;
        to.y = to.y + humanFingerChubbiness;
    }

    if (!duration) {
        UIATarget.localTarget().flickFromTo(point, to);
    }
    else {
        UIATarget.localTarget().dragFromToForDuration(point, to, duration);
    }
    wait(2);
}

/// Find an element whose name contains str within element.
/// If allowCache is true, it might re-use the result at any level during the last childrenArray calls
function findChild(element, str, allowCache) {
    var splitIdx = str.indexOf("::");
    if (splitIdx>=0) {
        var items = str.split("::");
        var first = findChild(element, items[0], allowCache);
        if (!first) return null;
        return findChild(first, str.substring(splitIdx+2), allowCache);
    }

    var realtype = null;
    var realstr = str;

    var reg = /^\(\((.*)\)\)(.*)/;
    var rmatch = reg.exec(str);
    if (rmatch) {
        realtype = rmatch[1];
        realstr = rmatch[2];
    }

    var skipCount = 0;
    var reg2 = /(.*)\[\[(\d+)\]\]$/;
    var rmatch2 = reg2.exec(realstr);
    if (rmatch2) {
        realstr = rmatch2[1];
        skipCount = parseInt(rmatch2[2]);
    }

    var array = childrenArray(element, allowCache);
    for (var i in array) {
        var element = array[i];
        if (!inScreen(element)) {
            continue;
        }
        var match = true;
        if (realstr.length) {
            if (!element.name()) {
                match = false;
            }
            else if (element.name().indexOf(realstr)<0) {
                match = false;
            }
        }
        if (realtype) {
            var info = " "+element;
            if (info.indexOf(realtype)<0) {
                match = false;
            }
        }
        if (match) {
            if (skipCount>0) {
                skipCount --;
            }
            else {
                return element;
            }
        }
    }
    return null;
}

/// Current time in seconds
function currentTimeInSec() {
    return (new Date().getTime() / 1000);
}

/// Allowing a maximum waiting time, and check whether the target element appears
/// Returns the element if it exists.
function waitForElement(target, maxTime) {
    var window = win();
    var child = findChild(window, target);
    var timeStarted = currentTimeInSec();
    var timeSpent = 0;
    while(!child && timeSpent<maxTime) {
        wait(1);
        child = findChild(window, target);
        timeSpent = currentTimeInSec() - timeStarted;
    }
    return child;
}

/// Perform task based on task array
function performTask(tasks) {
    if (!GlobalEnv.Pass) {
        return;
    }

    for (var i in tasks) {
        wait(1); // be tolerant at the beginning

        var step  = tasks[i];
        log("performing "+step);

        var missing = performStep(step);

        if (missing) {
            break;
        }
    }
    if (missing) {
        log("[error] cannot find or interact with "+ missing + " during step " + step);
        UIALogger.logFail("fail to find or interact with "+ missing + " during step " + step);
        // throw "fail";
        GlobalEnv.Pass = false;
    }
}

function performStep(step) {
    var window = win();
    var action = step[0];
    var missing = null;
    var rescueIdx = -1;

    bustChildArrayCache();

    if (Check == action) {
        waitForElement(step[1], GlobalEnv.DefaultMaxWaitingTime);
        for (var j in step) {
            if (j>0) {
                if (!findChild(window, step[j], true)) {
                    missing = step[j];
                    break;
                }
            }
        }

    }
    else if (Tap == action || TryTap == action) {
        waitForElement(step[1], GlobalEnv.DefaultMaxWaitingTime);
        var b = findChild(window, step[1]);
        if (!b) {
            missing = step[1];
        }
        else {
            try {
                // log("going to tap " + b + b.name() + rect2str(b.rect()) );
                if (TryTap ==action) {
                    UIATarget.localTarget().tap(centerPoint(b.rect()));
                }
                else if (b instanceof UIAButton) {
                    b.tap();
                }
                else {
                    UIATarget.localTarget().tap(centerPoint(b.rect()));
                }
            }
            catch(ex) {
                missing = step[1];
            }
        }
        if (action== Tap) {
            rescueIdx = 2;
        }
        else { // TryTap
            if (missing) {
                log("Failed to tap "+missing+" but it is fine");
            }
            missing = null; // it's fine
        }
    }
    else if (Investigate == action) {
        if (step.length>1) {
            var e = findChild(window, step[1]);
            if (!e) {
                missing = step[1];
            }
            else {
                logTree(e);
            }
        }
        else {
            logTree(window);
            // UIATarget.localTarget().logElementTree();
        }
    }
    else if (Input == action) {
        var kb = UIATarget.localTarget().frontMostApp().keyboard();
        if (kb) {
            kb.typeString(step[1]);
        }
        else {
            missing = "Keyboard";
            rescueIdx = 2;
        }
    }
    else if (Wait == action) {
        wait(step[1]);
    }
    else if (Scroll == action) {
        var point = screenCenter();
        if (step[2]) {
            var element = findChild(window, step[2]);
            if (element) {
                point = centerPoint(element.rect());
            }
        }
        swipe(point, step[1], null, 1);
    }
    else if (Swipe == action) {
        var point = screenCenter();
        if (step[2]) {
            var element = findChild(window, step[2]);
            if (element) {
                point = centerPoint(element.rect());
            }
        }
        swipe(point, step[1]);
    }
    else if (TapPoint == action) {
        UIATarget.localTarget().tap(step[1]);
    }
    else if (WaitFor == action) {
        var target = step[1];
        var maxTime = step[2];
        var child = waitForElement(target, maxTime);
        if (!child) {
            missing = target;
            rescueIdx = 3;
        }
    }
    else if (Pick == action) {
        waitForElement(step[1], GlobalEnv.DefaultMaxWaitingTime);
        var picker = findChild(window, step[1]);
        if (!picker || !(picker instanceof UIAPickerWheel) ) {
            missing = step[1];
        }
        else {
            try {
                picker.selectValue(step[2]);
            }
            catch(ex) {
                missing = step[2];
            }
        }
        rescueIdx = 3;
    }

    // see if we can rescue
    if (missing && rescueIdx && step[rescueIdx]) {
        rescueTask = step[rescueIdx];
        step.splice(rescueIdx,1);
        wait(1);
        log("rescuing with "+rescueTask);
        var rescueMissing = performStep(rescueTask);
        if (!rescueMissing) {
            wait(1);
            log("retrying "+step);
            missing = performStep(step);
        }
    }

    return missing;
}

<commit_msg>Added a failure investigation step in case of failure.<commit_after>

/** @return true if the device is iPad or iPad simulator
 */
function isPad() {
    return UIATarget.localTarget().model().indexOf("iPad")>=0;
}

var Direction = {
    Up    : {value:0, name:"Up"},
    Down  : {value:1, name:"Down"},
    Left  : {value:3, name:"Left"},
    Right : {value:4, name:"Right"}
};

var Check = "check";
var Tap = "tap";
var TryTap = "tryTap";
var Investigate = "investigate";
var Input = "input";
var Wait = "wait";
var Scroll = "scroll";
var Swipe = "swipe";
var TapPoint = "tapPoint";
var WaitFor = "waitFor";
var Pick = "pick";

var GlobalEnv = {
    // Configs
    // Users can set these values
    DefaultMaxWaitingTime : 10,
    EnableTableGroup : false,

    // Results
    // gsautomation.js should write to these variables
    ChildrenArrayCache : {},
    Pass : true,
};

/// Shortcut for debug log
function log(str) {
	UIALogger.logDebug(str);
}

/// short cut for getting main window
function win() {
	return UIATarget.localTarget().frontMostApp().mainWindow();
}

/// short cut for delay
function wait(i) {
	UIATarget.localTarget().delay(i);
}

/** Checks if 2 elements overlap
 */
function overlap(element1, element2) {
    var rect1 = element1.rect();
    var rect2 = element2.rect();
    return (rect1.origin.x + rect1.size.width > rect2.origin.x && rect2.origin.x + rect2.size.width > rect1.origin.x
            && rect1.origin.y + rect1.size.height > rect2.origin.y && rect2.origin.y + rect2.size.height > rect1.origin.y);
}

/** return the center point of a rect, a dict with x and y
 */
function centerPoint(r) {
    return {x: (r.origin.x+r.size.width/2), y: (r.origin.y+r.size.height/2)};
}

/** return the screen center point, a dict with x and y
 */
function screenCenter() {
    var size = win().rect().size;
    return {x: size.width/2, y: size.height/2};
}

/** check if an element is inside screen
 */
function inScreen(element) {
    if (!element || !(element instanceof UIAElement)) return false;
    var size = element.rect().size;
	return overlap(element, win()) && size.width>0 && size.height>0;
}

/** converts a rect object to a string
 */
function rect2str(r) {
    return "(" + r.origin.x + ", " + r.origin.y + ") w=" + r.size.width + ", h="+ r.size.height;
}

/** Get an array of children for an element.
 * if allowCache is true, it might return the result from last childrenArray call
 */
function childrenArray(element, allowCache) {
    var elementText = debugText(element);
    if (allowCache) {
        var cachedArray = GlobalEnv.ChildrenArrayCache[elementText];
        if (cachedArray) {
            return cachedArray;
        }
    }
    var children = (element instanceof UIATableView)? element.visibleCells() : element.elements();
    var array = children.toArray();
    if (GlobalEnv.EnableTableGroup && (element instanceof UIATableView)) {
        var groups = element.groups(); // this call takes 5 sec for tables without groups..
        if (groups) {
            array = array.concat(groups.toArray());
        }
    }
    if (!array) {
        array = []; // at least make it an object so we can cache
    }
    GlobalEnv.ChildrenArrayCache[elementText] = array;
    return array;
}

function bustChildArrayCache() {
    GlobalEnv.ChildrenArrayCache = {};
}

/** Get the debug text of an element
 */
function debugText(element) {
    var text = "[" + element.name() + "] " + element + " @ " + rect2str(element.rect());
    return text;
}

/** Mark the result as passed or failed in instruments
 */
function displayResult() {
    if (GlobalEnv.Pass) {
        UIALogger.logPass("Passed all tests");
    }
    else {
        UIALogger.logFail("Failed");
    }
}

/// Safer than built-in logElementTree since this doesn't do recursion
function logChildren(element) {
    var array = childrenArray(element, false);
    for (var i in array) {
        var element = array[i];
        var prefix = inScreen(element)? "√ " : "X "
        log( prefix + debugText(element) );
    }
}

/// Safer than built-in logElementTree since this does recursion more conservatively
function logTree(element) {
    var stack = [element];
    var levelStack = [0];
    bustChildArrayCache();
    while (stack.length) {
        var current = stack.pop();
        var currentLevel = levelStack.pop();
        log("* " + Array(currentLevel).join("- ") + debugText(current));
        var children = childrenArray(current, true);
        for (var i in children.reverse()) {
            var child = children[i];
            if (inScreen(child) && !(child instanceof UIAApplication) ) {
                var childLevel = currentLevel + 1;
                levelStack.push(childLevel)
                stack.push(child);
            }
        }
    }
}

/** Swipe at a point to a direction
 * point is a dictionary with keys: x and y
 * direction is an instance of Direction enum
 */
function swipe(point, direction, distance, duration) {

    if (!distance) {
        distance = isPad() ? 300 : 100;
    }

    var humanFingerChubbiness = 5;
    var to = {};
    to.x = point.x;
    to.y = point.y;
    if (direction == Direction.Up) {
        to.y = to.y - distance;
        to.x = to.x + humanFingerChubbiness;
    }
    else if (direction == Direction.Down) {
        to.y = to.y + distance;
        to.x = to.x + humanFingerChubbiness;
    }
    else if (direction == Direction.Left) {
        to.x = to.x - distance;
        to.y = to.y + humanFingerChubbiness;
    }
    else if (direction == Direction.Right) {
        to.x = to.x + distance;
        to.y = to.y + humanFingerChubbiness;
    }

    if (!duration) {
        UIATarget.localTarget().flickFromTo(point, to);
    }
    else {
        UIATarget.localTarget().dragFromToForDuration(point, to, duration);
    }
    wait(2);
}

/// Find an element whose name contains str within element.
/// If allowCache is true, it might re-use the result at any level during the last childrenArray calls
function findChild(element, str, allowCache) {
    var splitIdx = str.indexOf("::");
    if (splitIdx>=0) {
        var items = str.split("::");
        var first = findChild(element, items[0], allowCache);
        if (!first) return null;
        return findChild(first, str.substring(splitIdx+2), allowCache);
    }

    var realtype = null;
    var realstr = str;

    var reg = /^\(\((.*)\)\)(.*)/;
    var rmatch = reg.exec(str);
    if (rmatch) {
        realtype = rmatch[1];
        realstr = rmatch[2];
    }

    var skipCount = 0;
    var reg2 = /(.*)\[\[(\d+)\]\]$/;
    var rmatch2 = reg2.exec(realstr);
    if (rmatch2) {
        realstr = rmatch2[1];
        skipCount = parseInt(rmatch2[2]);
    }

    var array = childrenArray(element, allowCache);
    for (var i in array) {
        var element = array[i];
        if (!inScreen(element)) {
            continue;
        }
        var match = true;
        if (realstr.length) {
            if (!element.name()) {
                match = false;
            }
            else if (element.name().indexOf(realstr)<0) {
                match = false;
            }
        }
        if (realtype) {
            var info = " "+element;
            if (info.indexOf(realtype)<0) {
                match = false;
            }
        }
        if (match) {
            if (skipCount>0) {
                skipCount --;
            }
            else {
                return element;
            }
        }
    }
    return null;
}

/// Current time in seconds
function currentTimeInSec() {
    return (new Date().getTime() / 1000);
}

/// Allowing a maximum waiting time, and check whether the target element appears
/// Returns the element if it exists.
function waitForElement(target, maxTime) {
    var window = win();
    var child = findChild(window, target);
    var timeStarted = currentTimeInSec();
    var timeSpent = 0;
    while(!child && timeSpent<maxTime) {
        wait(1);
        child = findChild(window, target);
        timeSpent = currentTimeInSec() - timeStarted;
    }
    return child;
}

/// Perform task based on task array
function performTask(tasks) {
    if (!GlobalEnv.Pass) {
        return;
    }

    for (var i in tasks) {
        wait(1); // be tolerant at the beginning

        var step  = tasks[i];
        log("performing "+step);

        var missing = performStep(step);

        if (missing) {
            break;
        }
    }
    if (missing) {
        log("[error] cannot find or interact with "+ missing + " during step: " + step);
        log("[failure investigation] current elements on screen");
        logTree(win());
        UIALogger.logFail("fail to find or interact with "+ missing + " during step: " + step);
        // throw "fail";
        GlobalEnv.Pass = false;
    }
}

function performStep(step) {
    var window = win();
    var action = step[0];
    var missing = null;
    var rescueIdx = -1;

    bustChildArrayCache();

    if (Check == action) {
        waitForElement(step[1], GlobalEnv.DefaultMaxWaitingTime);
        for (var j in step) {
            if (j>0) {
                if (!findChild(window, step[j], true)) {
                    missing = step[j];
                    break;
                }
            }
        }

    }
    else if (Tap == action || TryTap == action) {
        waitForElement(step[1], GlobalEnv.DefaultMaxWaitingTime);
        var b = findChild(window, step[1]);
        if (!b) {
            missing = step[1];
        }
        else {
            try {
                // log("going to tap " + b + b.name() + rect2str(b.rect()) );
                if (TryTap ==action) {
                    UIATarget.localTarget().tap(centerPoint(b.rect()));
                }
                else if (b instanceof UIAButton) {
                    b.tap();
                }
                else {
                    UIATarget.localTarget().tap(centerPoint(b.rect()));
                }
            }
            catch(ex) {
                missing = step[1];
            }
        }
        if (action== Tap) {
            rescueIdx = 2;
        }
        else { // TryTap
            if (missing) {
                log("Failed to tap "+missing+" but it is fine");
            }
            missing = null; // it's fine
        }
    }
    else if (Investigate == action) {
        if (step.length>1) {
            var e = findChild(window, step[1]);
            if (!e) {
                missing = step[1];
            }
            else {
                logTree(e);
            }
        }
        else {
            logTree(window);
            // UIATarget.localTarget().logElementTree();
        }
    }
    else if (Input == action) {
        var kb = UIATarget.localTarget().frontMostApp().keyboard();
        if (kb) {
            kb.typeString(step[1]);
        }
        else {
            missing = "Keyboard";
            rescueIdx = 2;
        }
    }
    else if (Wait == action) {
        wait(step[1]);
    }
    else if (Scroll == action) {
        var point = screenCenter();
        if (step[2]) {
            var element = findChild(window, step[2]);
            if (element) {
                point = centerPoint(element.rect());
            }
        }
        swipe(point, step[1], null, 1);
    }
    else if (Swipe == action) {
        var point = screenCenter();
        if (step[2]) {
            var element = findChild(window, step[2]);
            if (element) {
                point = centerPoint(element.rect());
            }
        }
        swipe(point, step[1]);
    }
    else if (TapPoint == action) {
        UIATarget.localTarget().tap(step[1]);
    }
    else if (WaitFor == action) {
        var target = step[1];
        var maxTime = step[2];
        var child = waitForElement(target, maxTime);
        if (!child) {
            missing = target;
            rescueIdx = 3;
        }
    }
    else if (Pick == action) {
        waitForElement(step[1], GlobalEnv.DefaultMaxWaitingTime);
        var picker = findChild(window, step[1]);
        if (!picker || !(picker instanceof UIAPickerWheel) ) {
            missing = step[1];
        }
        else {
            try {
                picker.selectValue(step[2]);
            }
            catch(ex) {
                missing = step[2];
            }
        }
        rescueIdx = 3;
    }

    // see if we can rescue
    if (missing && rescueIdx && step[rescueIdx]) {
        rescueTask = step[rescueIdx];
        step.splice(rescueIdx,1);
        wait(1);
        log("rescuing with "+rescueTask);
        var rescueMissing = performStep(rescueTask);
        if (!rescueMissing) {
            wait(1);
            log("retrying "+step);
            missing = performStep(step);
        }
    }

    return missing;
}

<|endoftext|>


<commit_before><commit_msg>NCI-Agency/anet#2780: Make sure label is updated when position type is changed<commit_after><|endoftext|>


<commit_before>"use strict";

import { MessageBroker } from "./../message_broker";
import { RoadNetwork } from "./../road_network";
import { Terrain } from "./../terrain";

import { CityConfigService } from "./city_config_service";
import { CityEditorController } from "./city_editor_controller";
import { MapCamera } from "./map_camera";
import { NavigationController } from "./navigation_controller";
import { NavigationTouchController } from "./navigation_touch_controller";
import { SceneView } from "./scene_view";
import { TimerLoop } from "./timer_loop";

import { WorldGenerator } from "./../generators/world_generator";

var App = (function() {
  var EMPTY_TERRAIN = Terrain([[]], 1);
  var EMPTY_WORLD_DATA = {
    terrain: EMPTY_TERRAIN,
    roadNetwork: RoadNetwork(EMPTY_TERRAIN),
    buildings: [],
    neighborhoods: [],
    centerX: undefined,
    centerZ: undefined,
  };

  var detectWebGL = function() {
    if (!window.WebGLRenderingContext) {
      return false;
    }

    // Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/webgl-extensions.js
    var canvas = document.createElement('canvas');
    var webgl_context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    if (webgl_context === null) {
      return false;
    }

    return true;
  };

  var showLoadFailureMessage = function() {
    var loadingMessage = document.getElementById("loading-message");
    loadingMessage.innerText = "This site is not compatible with your browser, because it requires WebGL.";
    loadingMessage.classList.add("flex");
    loadingMessage.classList.remove("display-none");
  };

  var init = function(gridTexture) {
    if (!detectWebGL()) {
      showLoadFailureMessage();
      return;
    }

    var container = document.getElementById("container");

    var messageBroker = new MessageBroker();
    var cityConfigService = new CityConfigService();
    var sceneView = new SceneView(document.documentElement, gridTexture);
    var mapCamera = new MapCamera(sceneView, EMPTY_WORLD_DATA.terrain, messageBroker);
    var timerLoop = new TimerLoop(EMPTY_WORLD_DATA, sceneView, mapCamera, messageBroker);
    var cityEditorController = new CityEditorController(cityConfigService, messageBroker);
    var navigationController = new NavigationController(sceneView, mapCamera, EMPTY_WORLD_DATA.terrain, timerLoop, messageBroker);
    var navigationTouchController = new NavigationTouchController(sceneView, mapCamera, EMPTY_WORLD_DATA.terrain, messageBroker);

    container.appendChild(sceneView.domElement());

    var resetCity = function(data) {
      console.log("Starting city generation");
      var startTime = new Date();
      var endTime;
      var renderStartTime, renderEndTime;
      var newWorldData;

      mapCamera.reset();

      // Replace old scene with mostly empty scene, to reclaim memory.
      // A device with limited memory (such as a phone) might have enough
      // memory to have a single city, but not two at once (which can
      // temporarily be the case while creating a new city).
      timerLoop.reset(EMPTY_WORLD_DATA);
      sceneView.reset(EMPTY_WORLD_DATA);
      mapCamera.setTerrain(EMPTY_WORLD_DATA.terrain);
      navigationController.setTerrain(EMPTY_WORLD_DATA.terrain);
      navigationTouchController.setTerrain(EMPTY_WORLD_DATA.terrain);

      // Now that old city's memory has been reclaimed, add new city
      newWorldData = WorldGenerator.generate(cityConfigService.toWorldConfig());
      timerLoop.reset(newWorldData);
      sceneView.reset(newWorldData);
      mapCamera.setTerrain(newWorldData.terrain);
      navigationController.setTerrain(newWorldData.terrain);
      navigationTouchController.setTerrain(newWorldData.terrain);

      // Force the new scene to be rendered
      renderStartTime = new Date();
      sceneView.resize();
      renderEndTime = new Date();
      console.log("Time to perform initial render: " + (renderEndTime - renderStartTime) + "ms");

      endTime = new Date();
      console.log("City generation complete, total time: " + (endTime - startTime) + "ms");

      messageBroker.publish("generation.complete", {});
    };

    messageBroker.addSubscriber("generation.started", resetCity);

    resetCity();
  };

  return {
    init: init,
  };
})();

new THREE.TextureLoader().load("textures/grid.png", function(gridTexture) {
  App.init(gridTexture);
});
<commit_msg>Extracting function, to remove code duplication<commit_after>"use strict";

import { MessageBroker } from "./../message_broker";
import { RoadNetwork } from "./../road_network";
import { Terrain } from "./../terrain";

import { CityConfigService } from "./city_config_service";
import { CityEditorController } from "./city_editor_controller";
import { MapCamera } from "./map_camera";
import { NavigationController } from "./navigation_controller";
import { NavigationTouchController } from "./navigation_touch_controller";
import { SceneView } from "./scene_view";
import { TimerLoop } from "./timer_loop";

import { WorldGenerator } from "./../generators/world_generator";

var App = (function() {
  var EMPTY_TERRAIN = Terrain([[]], 1);
  var EMPTY_WORLD_DATA = {
    terrain: EMPTY_TERRAIN,
    roadNetwork: RoadNetwork(EMPTY_TERRAIN),
    buildings: [],
    neighborhoods: [],
    centerX: undefined,
    centerZ: undefined,
  };

  var detectWebGL = function() {
    if (!window.WebGLRenderingContext) {
      return false;
    }

    // Adapted from https://github.com/Modernizr/Modernizr/blob/master/feature-detects/webgl-extensions.js
    var canvas = document.createElement('canvas');
    var webgl_context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
    if (webgl_context === null) {
      return false;
    }

    return true;
  };

  var showLoadFailureMessage = function() {
    var loadingMessage = document.getElementById("loading-message");
    loadingMessage.innerText = "This site is not compatible with your browser, because it requires WebGL.";
    loadingMessage.classList.add("flex");
    loadingMessage.classList.remove("display-none");
  };

  var init = function(gridTexture) {
    if (!detectWebGL()) {
      showLoadFailureMessage();
      return;
    }

    var container = document.getElementById("container");

    var messageBroker = new MessageBroker();
    var cityConfigService = new CityConfigService();
    var sceneView = new SceneView(document.documentElement, gridTexture);
    var mapCamera = new MapCamera(sceneView, EMPTY_WORLD_DATA.terrain, messageBroker);
    var timerLoop = new TimerLoop(EMPTY_WORLD_DATA, sceneView, mapCamera, messageBroker);
    var cityEditorController = new CityEditorController(cityConfigService, messageBroker);
    var navigationController = new NavigationController(sceneView, mapCamera, EMPTY_WORLD_DATA.terrain, timerLoop, messageBroker);
    var navigationTouchController = new NavigationTouchController(sceneView, mapCamera, EMPTY_WORLD_DATA.terrain, messageBroker);

    container.appendChild(sceneView.domElement());

    var resetCity = function(data) {
      console.log("Starting city generation");
      var startTime = new Date();
      var endTime;
      var renderStartTime, renderEndTime;
      var newWorldData;

      mapCamera.reset();

      // Replace old scene with mostly empty scene, to reclaim memory.
      // A device with limited memory (such as a phone) might have enough
      // memory to have a single city, but not two at once (which can
      // temporarily be the case while creating a new city).
      setWorldData(EMPTY_WORLD_DATA);

      // Now that old city's memory has been reclaimed, add new city
      newWorldData = WorldGenerator.generate(cityConfigService.toWorldConfig());
      setWorldData(newWorldData);

      // Force the new scene to be rendered
      renderStartTime = new Date();
      sceneView.resize();
      renderEndTime = new Date();
      console.log("Time to perform initial render: " + (renderEndTime - renderStartTime) + "ms");

      endTime = new Date();
      console.log("City generation complete, total time: " + (endTime - startTime) + "ms");

      messageBroker.publish("generation.complete", {});
    };

    var setWorldData = function(newWorldData) {
      timerLoop.reset(newWorldData);
      sceneView.reset(newWorldData);
      mapCamera.setTerrain(newWorldData.terrain);
      navigationController.setTerrain(newWorldData.terrain);
      navigationTouchController.setTerrain(newWorldData.terrain);
    };

    messageBroker.addSubscriber("generation.started", resetCity);

    resetCity();
  };

  return {
    init: init,
  };
})();

new THREE.TextureLoader().load("textures/grid.png", function(gridTexture) {
  App.init(gridTexture);
});
<|endoftext|>


<commit_before>angular.module( 'ngBoilerplate', [
  'templates-app',
  'templates-common',
  'ngBoilerplate.home',
  'service.GameManager',
  'service.Keyboard',
  'ui.router'
])

.config( function myAppConfig ( $stateProvider, $urlRouterProvider ) {
  $urlRouterProvider.otherwise( '/home' );
})

.run( function run () {
})

.controller( 'AppCtrl', [
    '$scope',
    'GameManager',
    'KeyboardService',
function(
    $scope,
    GameManager,
    KeyboardService
){

    function exceptConituneKey(event) {
        switch(KeyboardService.getKey(event.which)) {
            case 'esc':
            case 'p':
                $scope.$broadcast('app.pause');
                return true;
            default:
                return false;
        }
    }

    $scope.keydown = function keydown($event) {
        if (exceptConituneKey($event) ||
            (GameManager.isGameStart() && !GameManager.isPause())) {
            KeyboardService.keydownAction($event);
        }
    };

    $scope.importTrackingScript = function importTrackingScript() {
        if (window.location.origin.indexOf('localhost') !== -1) {
            return false;
        } else {
            return true;
        }
    };
}]);<commit_msg>rename the app<commit_after>angular.module( 'ngTetris', [
  'templates-app',
  'templates-common',
  'ngTetris.home',
  'service.GameManager',
  'service.Keyboard',
  'ui.router'
])

.config( function myAppConfig ( $stateProvider, $urlRouterProvider ) {
  $urlRouterProvider.otherwise( '/home' );
})

.run( function run () {
})

.controller( 'AppCtrl', [
    '$scope',
    'GameManager',
    'KeyboardService',
function(
    $scope,
    GameManager,
    KeyboardService
){

    function exceptConituneKey(event) {
        switch(KeyboardService.getKey(event.which)) {
            case 'esc':
            case 'p':
                $scope.$broadcast('app.pause');
                return true;
            default:
                return false;
        }
    }

    $scope.keydown = function keydown($event) {
        if (exceptConituneKey($event) ||
            (GameManager.isGameStart() && !GameManager.isPause())) {
            KeyboardService.keydownAction($event);
        }
    };

    $scope.importTrackingScript = function importTrackingScript() {
        if (window.location.origin.indexOf('localhost') !== -1) {
            return false;
        } else {
            return true;
        }
    };
}]);<|endoftext|>


<commit_before>define(function module(require) { "use strict"

  var withAdvice = require('./../lib/flight/advice').withAdvice;

  var BaseSet = function() { this.initialize.apply(this, arguments); };

  BaseSet.prototype.initialize = function(val) {
    this.set = new Set();
    this.downstream = [];
  };
  BaseSet.prototype.add = function(item) {
    this.downstream.forEach(function(ea) { ea.newItem(item); });
    return this.set.add(item);
  };
  BaseSet.prototype.delete = function(item) {
    this.downstream.forEach(function(ea) { ea.destroyItem(item); });
    return this.set.delete(item);
  };

  return BaseSet;
});
<commit_msg>baseset as class<commit_after>define(function module(require) { "use strict"

  var withAdvice = require('./../lib/flight/advice').withAdvice;

  var BaseSet = Object.subclass('BaseSet', {
    initialize: function(val) {
      this.set = new Set();
      this.downstream = [];
    },
    add: function(item) {
      this.downstream.forEach(function(ea) { ea.newItem(item); });
      return this.set.add(item);
    },
    delete: function(item) {
      this.downstream.forEach(function(ea) { ea.destroyItem(item); });
      return this.set.delete(item);
    }
  });

  return BaseSet;
});
<|endoftext|>


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

import chalk from 'chalk';
import meow from 'meow';
import {ncp} from 'ncp';
import pify from 'pify';
import formatPath from '../lib/formatPath';
import prepareProblem from '../lib/prepareProblem';
import prepareSolution from '../lib/prepareSolution';

const problemify = async function (srcDir, destDir, cb) {
  // match root directory name without slashes
  const regex = /.*?\/*([^<>:"\/\\|?*]+)\/*$/;
  const rootDirname = srcDir.replace(regex, '$1');
  const ncpOptions = {
    stopOnErr: true,
    // filter pathnames that contain '.git'
    filter(input) {
      return !(/\.git/g.test(input));
    },
    transform(fileReadable, fileWriteable) {
      fileReadable.on('data', chunk => fileWriteable.write(cb(chunk.toString())));
      fileReadable.on('error', err => console.error(err));
      fileWriteable.on('error', err => console.error(err));
      fileReadable.on('end', () => {
        const srcName = fileReadable.path;
        const srcIndex = srcName.lastIndexOf(rootDirname);
        const destName = fileWriteable.path;
        const destIndex = destName.lastIndexOf(rootDirname);
        console.log(`${srcName.slice(srcIndex)} → ${destName.slice(destIndex)}`);
        fileWriteable.end();
      });
    }
  };

  await pify(ncp)(srcDir, destDir, ncpOptions);
};

const cli = meow(`
  Usage
    $ problemify <directory>

  Example
    $ problemify death-star-plans
    $ ls
    death-star-plans  death-star-plans-problem  death-star-plans-solution
`);

const cliInput = formatPath(cli.input[0]);
const problemDest = `${cliInput}-problem`;
const solutionDest = `${cliInput}-solution`;

(async () => {
  try {
    await problemify(cliInput, problemDest, prepareProblem);
    await problemify(cliInput, solutionDest, prepareSolution);
  } catch (err) {
    console.log(chalk.yellow("Something went wrong. See 'problemify --help' for usage information."));
    console.error(chalk.red(err.stack || err));
    process.exit(1);
  }
})();
<commit_msg>Concatenate data chunks<commit_after>#!/usr/bin/env node

import chalk from 'chalk';
import meow from 'meow';
import {ncp} from 'ncp';
import pify from 'pify';
import formatPath from '../lib/formatPath';
import prepareProblem from '../lib/prepareProblem';
import prepareSolution from '../lib/prepareSolution';

const problemify = async function (srcDir, destDir, cb) {
  // match root directory name without slashes
  const regex = /.*?\/*([^<>:"\/\\|?*]+)\/*$/;
  const rootDirname = srcDir.replace(regex, '$1');
  const ncpOptions = {
    stopOnErr: true,
    // filter pathnames that contain '.git'
    filter(input) {
      return !(/\.git/g.test(input));
    },
    transform(fileReadable, fileWriteable) {
      let file = '';
      fileReadable.on('data', chunk => {
        file += chunk;
      });

      fileReadable.on('end', () => {
        fileWriteable.write(cb(file));
        const srcName = fileReadable.path;
        const srcIndex = srcName.lastIndexOf(rootDirname);
        const destName = fileWriteable.path;
        const destIndex = destName.lastIndexOf(rootDirname);
        console.log(`${srcName.slice(srcIndex)} → ${destName.slice(destIndex)}`);
        fileWriteable.end();
      });

      fileReadable.on('error', err => console.error(err));
      fileWriteable.on('error', err => console.error(err));
    }
  };

  await pify(ncp)(srcDir, destDir, ncpOptions);
};

const cli = meow(`
  Usage
    $ problemify <directory>

  Example
    $ problemify death-star-plans
    $ ls
    death-star-plans  death-star-plans-problem  death-star-plans-solution
`);

const cliInput = formatPath(cli.input[0]);
const problemDest = `${cliInput}-problem`;
const solutionDest = `${cliInput}-solution`;

(async () => {
  try {
    await problemify(cliInput, problemDest, prepareProblem);
    await problemify(cliInput, solutionDest, prepareSolution);
  } catch (err) {
    console.log(chalk.yellow("Something went wrong. See 'problemify --help' for usage information."));
    console.error(chalk.red(err.stack || err));
    process.exit(1);
  }
})();
<|endoftext|>


<commit_before>$(document).ready(function() {
    'use strict';

    var plus = false;
    var src_height = 380;

    var siteurl = $('.video-social').data('siteurl');

    // Fetch items
    var items = {
        getItems: function(data) {
            var url = '/items/' + data.category + '/' + data.timestamp + '/' + data.year + '/';
            var opts = {
                url: url
            };
            return $.ajax(opts, function() {}, function(error) {
                console.error('Error fetching', error);
            });
        },
        getItem: function(data) {
            var url = '/item/' + data.id + '/';
            var opts = {
                url: url
            };
            return $.ajax(opts, function() {}, function(error) {
                console.error('Error fetching', error);
            });
        },
    };

    function detail_load(id) {
        plus = false;
        var source = $('#details-source');
        var info = $('#details-info');
        source.html('
LOADING...
');
        info.html('');
        items.getItem({
            id: id
        }).done(function(item) {
            var source_html = ``;
            var info_html = ``;
            if (item.fields.category == 'Photo') {
                source_html = `

                `;
            } else {
                var source = '';
                if (item.fields.source) {
                    source = item.fields.source
                } else {
                    source = item.fields.source_large;
                }
                source_html = `
                    <video id="details-src" controls class="img-responsive">
                      <source src="/media/${source}">
                    </video>

                `;
            }
            source.html(source_html);

            source.ready(function() {
                var target = $('#details');
                $('html, body').animate({
                    show: target,
                    scrollTop: $(target).offset().top - 220
                }, 1000);
                info_html += `<div class="gallery-details-text" id="detail-${item.pk}" data-timestamp="${item.fields.timestamp}">`;
                if (item.fields.social_graph) {
                    info_html += `

                    `;
                } else {
                    info_html += `

                    `;
                }
                var created = moment(item.fields.created).format('MMMM D, YYYY');
                if (item.fields.pick_date == 'Year') {
                    created = moment(item.fields.created).format('YYYY');
                }
                if (item.fields.pick_date == 'YearMonth') {
                    created = moment(item.fields.created).format('MMMM, YYYY');
                }
                if (item.fields.social_graph) {
                    info_html += `

${item.fields.title}

                          ${created}

                    `;
                } else {
                    info_html += `

${item.fields.title}

                          ${created}

                    `;
                }
                if (item.fields.location) {
                    info_html += `

                          Location:
                          ${item.fields.location}

                    `;
                }
                if (item.fields.credit) {
                    info_html += `

                          Creator:
                          ${item.fields.credit}
                    `;
                    if (item.fields.creator_url) {
                        info_html += `

                        `;
                    }
                    info_html += `</div>`;
                }
                if (item.fields.comment) {
                    comment = item.fields.comment;
                    info_html += `

                          Description:
                          ${comment}

                    `;

                }
                info_html += `</div>`;
                var bottom_html = `<div class="details-bottom">`;
                bottom_html += `

                `;
                var item_title = item.fields.title.replace(/["']/g, "");
                bottom_html += `

                `;
                bottom_html += `</div>`;
                info.html('

');
                function details_content() {
                    info.html(info_html + bottom_html);
                    src_height = $('#details-src').height();
                    var width = $('.gallery-cat').width();
                    $('.details-bottom').css('width', width);
                    $('#details-info').css('height', src_height);
                    $('.gallery-details-text').css('height', src_height - 30);
                    $('.gallery-details-text').css('overflow', 'hidden');
                }
                var refreshId = setInterval(function() {
                    var check_height = 300;
                    if (screen.width < 950) {
                        check_height = 220;
                    }
                    if ($('#details-src').height() > check_height) {
                        clearInterval(refreshId);
                        details_content();
                    }
                }, 1000);
            });
        });
    }

    // Initiate Item details
    $('body').on('itemsloaded', function() {
        $('.details').on('click', function(event) {
            event.preventDefault();
            var id = $(this).data('id');
            var loc = window.location.href;
            window.location.hash = id;
            detail_load(id);
        });
    });

    // Render gallery
    var render = function(params) {
        var elements = '';

        if (params.length) {
            params.forEach(function(item) {
                var element = `

${item.fields.title}

                `;
                var pubdate = ``;
                var created = moment(item.fields.created).format('MMMM D, YYYY');
                if (item.fields.pick_date == 'Year') {
                    created = moment(item.fields.created).format('YYYY');
                }
                if (item.fields.pick_date == 'YearMonth') {
                    created = moment(item.fields.created).format('MMMM, YYYY');
                }
                if (item.fields.social_graph) {
                    pubdate = `

${created}

                    `;
                } else {
                    pubdate = `

${created}

                    `;
                }
                if (item.fields.category == 'Photo') {
                    var cat_icon = `

                    `;
                } else {
                    var cat_icon = `

                    `;
                }
                elements += (element + pubdate + cat_icon);
            });
        } else {
            elements = `

                No Gallery items on this location or year yet.

                Upload your archives.

`;
        }

        var rendered = `${elements}`;

        return rendered;
    };

    var gallery = $('#gallery-items');
    var category = $(gallery).data('category');
    var comment = '';
    var short_comment = '';

    // Filter by year
    $('.year-pick').on('click', function(event) {
        event.preventDefault();
        gallery.html('
LOADING...
');
        currentYear = $(this).data('year');
        $('#years > img').attr('src', '/static/img/years_' + currentYear + '.png');
        items.getItems({
            category: category,
            timestamp: currentTime,
            year: currentYear
        }).done(function(data) {
            gallery.html(render(data));
            $('body').trigger('itemsloaded');
        });
    });

    function show_full_comment() {
        $('#details-info').css('height', 'auto');
        $('.gallery-details-text').css('height', 'auto');
        $('.gallery-details-text').css('overflow', 'show');
        $('.details-bottom').css('position', 'relative');
        plus = true;
    }

    function hide_full_comment() {
        $('#details-info').css('height', src_height);
        $('.gallery-details-text').css('height', src_height - 30);
        $('.gallery-details-text').css('overflow', 'hidden');
        $('.details-bottom').css('position', 'absolute');
        plus = false;
    }

    // Show full comment
    $(document).on('click', '#comment-plus', function(event) {
        event.preventDefault();
        var plus_pos = $('.details-bottom').position().top;
        console.log(plus_pos);
        if (plus) {
            hide_full_comment();
        } else {
            show_full_comment();
            var new_plus_pos = $('.details-bottom').position().top;
            console.log(new_plus_pos);
            if (new_plus_pos < plus_pos) {
                hide_full_comment();
                plus = false;
            }
        }
    });

    // Select all things
    var pop = document.getElementById("thevideo");
    var route = $('.route');
    var route_title = $('.route-title');
    var elm_gallery = $('#gallery');
    var elm_strip = $('#gallery-strip');
    var elm_back = $('#video-back');
    var elm_detailsSource = $('#details-source');
    var elm_detailsInfo = $('#details-info');

    // Keep the moments
    var currentTime;
    var currentYear = 2008;

    // Back to video
    $(document).on('click', '#video-back', function () {
        $('body, html').animate({
            scrollTop: 0
        }, 800);
        pop.play();
        return false;
    });

    // Catch pause event and send over the current position
    pop.onpause = function() {
        currentTime = this.currentTime;
        elm_gallery.slideDown();
        elm_strip.slideDown();
        route.hide();
        route_title.hide();
        $('#years > img').attr('src', '/static/img/years_' + currentYear + '.png');
        items.getItems({
            category: category,
            timestamp: currentTime,
            year: currentYear
        }).done(function(data) {
            if (Modernizr.templatestrings) {
                gallery.html(render(data));
                $('body').trigger('itemsloaded');
            } else {
                gallery.html('
Please update your browser to the latest version, or use a more modern one like Firefox
');
            }
        });
        var help = `<a href="#" id="help-play">Play to go to map</a>`;
        $('.video-help').html(help);
        $('img[usemap]').rwdImageMaps();
    };

    // Hide elements on play
    pop.onplay = function() {
        route.show();
        route_title.show();
        elm_gallery.slideUp();
        elm_strip.slideUp();
        elm_detailsSource.text('');
        elm_detailsInfo.text('');
        elm_back.slideUp();
        $('#details-info').css('height', 'auto');
        $('.gallery-details-text').css('height', 'auto');
        var help = `Click on the map to go to riot zones and pause to go to galleries`;
        $('.video-help').html(help);
        $('img[usemap]').rwdImageMaps();
    };

    // Start the video
    pop.volume = 0.4;

    // Jump on map
    $('.route-pick').on('click', function(event) {
        event.preventDefault();
        var point = $(this).data('point');
        pop.currentTime = point;
        var help = `<a href="#" id="help-pause">Pause video to go to galleries</a>`;
        $('.video-help').html(help);
        $('body, html').animate({
            scrollTop: 0
        }, 800);
    });

    $(document).on('click', '#help-pause', function(event) {
        event.preventDefault();
        pop.pause();
    });

    $(document).on('click', '#help-play', function(event) {
        event.preventDefault();
        pop.play();
    });

    // Responsive map
    $('img[usemap]').rwdImageMaps();

    var uri = URI(location.href);
    var item_pick = uri.hash().split('#')[1];
    if (item_pick) {
        detail_load(item_pick);
        pop.pause();
    }
});
<commit_msg>Fix large videos js<commit_after>$(document).ready(function() {
    'use strict';

    var plus = false;
    var src_height = 380;

    var siteurl = $('.video-social').data('siteurl');

    // Fetch items
    var items = {
        getItems: function(data) {
            var url = '/items/' + data.category + '/' + data.timestamp + '/' + data.year + '/';
            var opts = {
                url: url
            };
            return $.ajax(opts, function() {}, function(error) {
                console.error('Error fetching', error);
            });
        },
        getItem: function(data) {
            var url = '/item/' + data.id + '/';
            var opts = {
                url: url
            };
            return $.ajax(opts, function() {}, function(error) {
                console.error('Error fetching', error);
            });
        },
    };

    function detail_load(id) {
        plus = false;
        var source = $('#details-source');
        var info = $('#details-info');
        source.html('
LOADING...
');
        info.html('');
        items.getItem({
            id: id
        }).done(function(item) {
            var source_html = ``;
            var info_html = ``;
            if (item.fields.category == 'Photo') {
                source_html = `

                `;
            } else {
                var source_url = '';
                if (item.fields.source) {
                    source_url = item.fields.source
                } else {
                    source_url = item.fields.source_large;
                }
                source_html = `
                    <video id="details-src" controls class="img-responsive">
                      <source src="/media/${source_url}">
                    </video>

                `;
            }
            source.html(source_html);

            source.ready(function() {
                var target = $('#details');
                $('html, body').animate({
                    show: target,
                    scrollTop: $(target).offset().top - 220
                }, 1000);
                info_html += `<div class="gallery-details-text" id="detail-${item.pk}" data-timestamp="${item.fields.timestamp}">`;
                if (item.fields.social_graph) {
                    info_html += `

                    `;
                } else {
                    info_html += `

                    `;
                }
                var created = moment(item.fields.created).format('MMMM D, YYYY');
                if (item.fields.pick_date == 'Year') {
                    created = moment(item.fields.created).format('YYYY');
                }
                if (item.fields.pick_date == 'YearMonth') {
                    created = moment(item.fields.created).format('MMMM, YYYY');
                }
                if (item.fields.social_graph) {
                    info_html += `

${item.fields.title}

                          ${created}

                    `;
                } else {
                    info_html += `

${item.fields.title}

                          ${created}

                    `;
                }
                if (item.fields.location) {
                    info_html += `

                          Location:
                          ${item.fields.location}

                    `;
                }
                if (item.fields.credit) {
                    info_html += `

                          Creator:
                          ${item.fields.credit}
                    `;
                    if (item.fields.creator_url) {
                        info_html += `

                        `;
                    }
                    info_html += `</div>`;
                }
                if (item.fields.comment) {
                    comment = item.fields.comment;
                    info_html += `

                          Description:
                          ${comment}

                    `;

                }
                info_html += `</div>`;
                var bottom_html = `<div class="details-bottom">`;
                bottom_html += `

                `;
                var item_title = item.fields.title.replace(/["']/g, "");
                bottom_html += `

                `;
                bottom_html += `</div>`;
                info.html('

');
                function details_content() {
                    info.html(info_html + bottom_html);
                    src_height = $('#details-src').height();
                    var width = $('.gallery-cat').width();
                    $('.details-bottom').css('width', width);
                    $('#details-info').css('height', src_height);
                    $('.gallery-details-text').css('height', src_height - 30);
                    $('.gallery-details-text').css('overflow', 'hidden');
                }
                var refreshId = setInterval(function() {
                    var check_height = 300;
                    if (screen.width < 950) {
                        check_height = 220;
                    }
                    if ($('#details-src').height() > check_height) {
                        clearInterval(refreshId);
                        details_content();
                    }
                }, 1000);
            });
        });
    }

    // Initiate Item details
    $('body').on('itemsloaded', function() {
        $('.details').on('click', function(event) {
            event.preventDefault();
            var id = $(this).data('id');
            var loc = window.location.href;
            window.location.hash = id;
            detail_load(id);
        });
    });

    // Render gallery
    var render = function(params) {
        var elements = '';

        if (params.length) {
            params.forEach(function(item) {
                var element = `

${item.fields.title}

                `;
                var pubdate = ``;
                var created = moment(item.fields.created).format('MMMM D, YYYY');
                if (item.fields.pick_date == 'Year') {
                    created = moment(item.fields.created).format('YYYY');
                }
                if (item.fields.pick_date == 'YearMonth') {
                    created = moment(item.fields.created).format('MMMM, YYYY');
                }
                if (item.fields.social_graph) {
                    pubdate = `

${created}

                    `;
                } else {
                    pubdate = `

${created}

                    `;
                }
                if (item.fields.category == 'Photo') {
                    var cat_icon = `

                    `;
                } else {
                    var cat_icon = `

                    `;
                }
                elements += (element + pubdate + cat_icon);
            });
        } else {
            elements = `

                No Gallery items on this location or year yet.

                Upload your archives.

`;
        }

        var rendered = `${elements}`;

        return rendered;
    };

    var gallery = $('#gallery-items');
    var category = $(gallery).data('category');
    var comment = '';
    var short_comment = '';

    // Filter by year
    $('.year-pick').on('click', function(event) {
        event.preventDefault();
        gallery.html('
LOADING...
');
        currentYear = $(this).data('year');
        $('#years > img').attr('src', '/static/img/years_' + currentYear + '.png');
        items.getItems({
            category: category,
            timestamp: currentTime,
            year: currentYear
        }).done(function(data) {
            gallery.html(render(data));
            $('body').trigger('itemsloaded');
        });
    });

    function show_full_comment() {
        $('#details-info').css('height', 'auto');
        $('.gallery-details-text').css('height', 'auto');
        $('.gallery-details-text').css('overflow', 'show');
        $('.details-bottom').css('position', 'relative');
        plus = true;
    }

    function hide_full_comment() {
        $('#details-info').css('height', src_height);
        $('.gallery-details-text').css('height', src_height - 30);
        $('.gallery-details-text').css('overflow', 'hidden');
        $('.details-bottom').css('position', 'absolute');
        plus = false;
    }

    // Show full comment
    $(document).on('click', '#comment-plus', function(event) {
        event.preventDefault();
        var plus_pos = $('.details-bottom').position().top;
        console.log(plus_pos);
        if (plus) {
            hide_full_comment();
        } else {
            show_full_comment();
            var new_plus_pos = $('.details-bottom').position().top;
            console.log(new_plus_pos);
            if (new_plus_pos < plus_pos) {
                hide_full_comment();
                plus = false;
            }
        }
    });

    // Select all things
    var pop = document.getElementById("thevideo");
    var route = $('.route');
    var route_title = $('.route-title');
    var elm_gallery = $('#gallery');
    var elm_strip = $('#gallery-strip');
    var elm_back = $('#video-back');
    var elm_detailsSource = $('#details-source');
    var elm_detailsInfo = $('#details-info');

    // Keep the moments
    var currentTime;
    var currentYear = 2008;

    // Back to video
    $(document).on('click', '#video-back', function () {
        $('body, html').animate({
            scrollTop: 0
        }, 800);
        pop.play();
        return false;
    });

    // Catch pause event and send over the current position
    pop.onpause = function() {
        currentTime = this.currentTime;
        elm_gallery.slideDown();
        elm_strip.slideDown();
        route.hide();
        route_title.hide();
        $('#years > img').attr('src', '/static/img/years_' + currentYear + '.png');
        items.getItems({
            category: category,
            timestamp: currentTime,
            year: currentYear
        }).done(function(data) {
            if (Modernizr.templatestrings) {
                gallery.html(render(data));
                $('body').trigger('itemsloaded');
            } else {
                gallery.html('
Please update your browser to the latest version, or use a more modern one like Firefox
');
            }
        });
        var help = `<a href="#" id="help-play">Play to go to map</a>`;
        $('.video-help').html(help);
        $('img[usemap]').rwdImageMaps();
    };

    // Hide elements on play
    pop.onplay = function() {
        route.show();
        route_title.show();
        elm_gallery.slideUp();
        elm_strip.slideUp();
        elm_detailsSource.text('');
        elm_detailsInfo.text('');
        elm_back.slideUp();
        $('#details-info').css('height', 'auto');
        $('.gallery-details-text').css('height', 'auto');
        var help = `Click on the map to go to riot zones and pause to go to galleries`;
        $('.video-help').html(help);
        $('img[usemap]').rwdImageMaps();
    };

    // Start the video
    pop.volume = 0.4;

    // Jump on map
    $('.route-pick').on('click', function(event) {
        event.preventDefault();
        var point = $(this).data('point');
        pop.currentTime = point;
        var help = `<a href="#" id="help-pause">Pause video to go to galleries</a>`;
        $('.video-help').html(help);
        $('body, html').animate({
            scrollTop: 0
        }, 800);
    });

    $(document).on('click', '#help-pause', function(event) {
        event.preventDefault();
        pop.pause();
    });

    $(document).on('click', '#help-play', function(event) {
        event.preventDefault();
        pop.play();
    });

    // Responsive map
    $('img[usemap]').rwdImageMaps();

    var uri = URI(location.href);
    var item_pick = uri.hash().split('#')[1];
    if (item_pick) {
        detail_load(item_pick);
        pop.pause();
    }
});
<|endoftext|>