<commit_before>/**
 * @author: Jerry Zou
 * @email: jerry.zry@outlook.com
 */

//= require jquery

(function($) {
    $.jUploader = function(options) {
        options = $.extend({
            url: '',
            buttonSelector: null,
            logSelector: null,
            fileSelector: null,
            singleSize: 4 * 1024 * 1024,    //default: 4MB
            chunkSize: 4 * 1024 * 1024,     //default: 4MB
            parallelRequest: 4,
            beforeSend: function() {},
            afterSuccess: function(total) {},
            chunkSuccess: function(index, completeNum, total) {}
        }, options);

        function log(content) {
            if (options.logSelector) {
                $(options.logSelector).append(content + '
');
            } else {
                console.log(content);
            }
        }

        $(options.buttonSelector).click(function() {
            var file = $(options.fileSelector)[0].files[0],
                name = file.name,
                size = file.size,
                succeed = 0,
                chunkSize = options.chunkSize,
                chunkNum = Math.ceil(size / chunkSize),
                begin = Date.now();

            log('Upload Begin: ' + new Date(begin).toLocaleTimeString());

            // if size of the file is no more than critical size
            if (size <= options.singleSize) {
                var form = new FormData();
                form.append("fileData", file);
                form.append("name", name);
                form.append("total", 1);
                form.append("index", 0);

                $.ajax({
                    url: options.url,
                    type: 'post',
                    data: form,
                    processData: false,
                    contentType: false,
                    beforeSend: function() {
                        log(name + ' begin sending!');
                        options.beforeSend();
                    },
                    success: function (response) {
                        if (JSON.parse(response)['OK']) {
                            log('Upload End: ' + new Date(Date.now()).toLocaleTimeString());
                            log('Takes: ' + (Date.now() - begin) + 'ms');
                            options.afterSuccess(1);
                        }
                        else {
                            log('Upload Error: ' + response);
                        }
                    },
                    error: function () {
                        log('Fail to connect to server');
                    }
                });
                return;
            }

            //chunk upload
            var sending = 0;
            for (; sending < 4; sending++) {
                uploadChunk(sending);
            }
            function uploadChunk(i) {
                var reader = new FileReader(),
                    start = i * chunkSize,
                    end = Math.min(size, start + chunkSize);

                reader.onloadend = function () {
                    $.ajax({
                        url: options.url,
                        type: 'post',
                        data: {
                            fileData: reader.result,
                            name: name,
                            total: chunkNum,
                            index: i
                        },
                        beforeSend: function() {
                            log('[index:' + i + '] begin sending!');
                            options.beforeSend();
                        },
                        success: function (response) {
                            if (JSON.parse(response)['OK']) {
                                options.chunkSuccess(i, ++succeed, chunkNum);
                                if (succeed === chunkNum) {
                                    log('Upload End: ' + new Date(Date.now()).toLocaleTimeString());
                                    log('Takes: ' + (Date.now() - begin) + 'ms');
                                    options.afterSuccess(chunkNum);
                                }
                                if (sending < chunkNum) {
                                    uploadChunk(sending++);
                                }
                            }
                            else {
                                log('Upload Error: ' + response);
                            }
                        },
                        error: function () {
                            log('Fail to connect to server');
                        }
                    });
                };
                reader.readAsDataURL(file.slice(start, end));
            }
        });
    };
}(jQuery));<commit_msg>modify error description<commit_after>/**
 * @author: Jerry Zou
 * @email: jerry.zry@outlook.com
 */

//= require jquery

(function($) {
    $.jUploader = function(options) {
        options = $.extend({
            url: '',
            buttonSelector: null,
            logSelector: null,
            fileSelector: null,
            singleSize: 4 * 1024 * 1024,    //default: 4MB
            chunkSize: 4 * 1024 * 1024,     //default: 4MB
            parallelRequest: 4,
            beforeSend: function() {},
            afterSuccess: function(total) {},
            chunkSuccess: function(index, completeNum, total) {}
        }, options);

        function log(content) {
            if (options.logSelector) {
                $(options.logSelector).append(content + '
');
            } else {
                console.log(content);
            }
        }

        $(options.buttonSelector).click(function() {
            var file = $(options.fileSelector)[0].files[0],
                name = file.name,
                size = file.size,
                succeed = 0,
                chunkSize = options.chunkSize,
                chunkNum = Math.ceil(size / chunkSize),
                begin = Date.now();

            log('Upload Begin: ' + new Date(begin).toLocaleTimeString());

            // if size of the file is no more than critical size
            if (size <= options.singleSize) {
                var form = new FormData();
                form.append("fileData", file);
                form.append("name", name);
                form.append("total", 1);
                form.append("index", 0);

                $.ajax({
                    url: options.url,
                    type: 'post',
                    data: form,
                    processData: false,
                    contentType: false,
                    beforeSend: function() {
                        log(name + ' begin sending!');
                        options.beforeSend();
                    },
                    success: function (response) {
                        if (JSON.parse(response)['OK']) {
                            log('Upload End: ' + new Date(Date.now()).toLocaleTimeString());
                            log('Takes: ' + (Date.now() - begin) + 'ms');
                            options.afterSuccess(1);
                        }
                        else {
                            log('Upload Error: ' + response);
                        }
                    },
                    error: function () {
                        log('ERROR: cannot connect to server');
                    }
                });
                return;
            }

            //chunk upload
            var sending = 0;
            for (; sending < 4; sending++) {
                uploadChunk(sending);
            }
            function uploadChunk(i) {
                var reader = new FileReader(),
                    start = i * chunkSize,
                    end = Math.min(size, start + chunkSize);

                reader.onloadend = function () {
                    $.ajax({
                        url: options.url,
                        type: 'post',
                        data: {
                            fileData: reader.result,
                            name: name,
                            total: chunkNum,
                            index: i
                        },
                        beforeSend: function() {
                            log('[index:' + i + '] begin sending!');
                            options.beforeSend();
                        },
                        success: function (response) {
                            if (JSON.parse(response)['OK']) {
                                options.chunkSuccess(i, ++succeed, chunkNum);
                                if (succeed === chunkNum) {
                                    log('Upload End: ' + new Date(Date.now()).toLocaleTimeString());
                                    log('Takes: ' + (Date.now() - begin) + 'ms');
                                    options.afterSuccess(chunkNum);
                                }
                                if (sending < chunkNum) {
                                    uploadChunk(sending++);
                                }
                            }
                            else {
                                log('Upload Error: ' + response);
                            }
                        },
                        error: function () {
                            log('ERROR: cannot connect to server');
                        }
                    });
                };
                reader.readAsDataURL(file.slice(start, end));
            }
        });
    };
}(jQuery));<|endoftext|>


<commit_before>
var RG = require('./rg.js');

RG.Object = require('./object.js');
RG.Component = require('./component.js');
RG.Brain = require('./brain.js');
RG.Inv = require('./inv.js');

RG.Actor = {};

/* Object representing a game actor who takes actions.  */
RG.Actor.Rogue = function(name) { // {{{2
    RG.Object.Locatable.call(this);
    RG.Entity.call(this);
    this.setPropType('actors');

    // Member vars
    this._brain = new RG.Brain.Rogue(this);
    this._brain.getMemory().addEnemyType('player');

    let _name = name;
    this._isPlayer = false;
    let _fovRange = RG.FOV_RANGE;

    this._invEq = new RG.Inv.Inventory(this);
    this._maxWeight = 10.0;

    // Components for this entity
    this.add('Action', new RG.Component.Action());
    this.add('Experience', new RG.Component.Experience());
    this.add('Combat', new RG.Component.Combat());
    this.add('Stats', new RG.Component.Stats());
    this.add('Health', new RG.Component.Health(50));

    this.setName = function(name) {_name = name;};
    this.getName = function() {return _name;};

    /* Returns true if actor is a player.*/
    this.isPlayer = function() {return this._isPlayer;};

    this.getFOVRange = function() { return _fovRange;};
    this.setFOVRange = function(range) {_fovRange = range;};

    //---------------------------------
    // Brain-relatd methods
    //---------------------------------

    this.addEnemy = function(actor) {this._brain.addEnemy(actor);};

    this.isEnemy = function(actor) {
        return this._brain.getMemory().isEnemy(actor);
    };

    this.getBrain = function() {return this._brain;};

    this.setBrain = function(brain) {
        this._brain = brain;
        this._brain.setActor(this);
    };

    //---------------------------------
    // Equipment related methods
    //---------------------------------

    this.getInvEq = function() { return this._invEq; };

    /* Returns weapon that is wielded by the actor.*/
    this.getWeapon = function() {return this._invEq.getWeapon();};

    /* Returns missile equipped by the player.*/
    this.getMissile = function() {
        return this._invEq.getEquipment().getItem('missile');
    };

    this.getEquipAttack = function() {
        return this._invEq.getEquipment().getAttack();
    };

    this.getEquipDefense = function() {
        return this._invEq.getEquipment().getDefense();
    };

    this.getEquipProtection = function() {
        return this._invEq.getEquipment().getProtection();
    };

};
RG.extend2(RG.Actor.Rogue, RG.Object.Locatable);
RG.extend2(RG.Actor.Rogue, RG.Entity);

/* Returns carrying capacity of the actor.*/
RG.Actor.Rogue.prototype.getMaxWeight = function() {
    var statStr = this.get('Stats').getStrength();
    var eqStr = this._invEq.getEquipment().getStrength();
    return 2 * statStr + 2 * eqStr + this._maxWeight;
};

/* Marks actor as player. Cannot unset player.*/
RG.Actor.Rogue.prototype.setIsPlayer = function(isPlayer) {
    if (isPlayer) {
        this._isPlayer = isPlayer;
        this._brain = new RG.Brain.Player(this);
        this.setType('player');
        this.add('StatsMods', new RG.Component.StatsMods());
        this.add('CombatMods', new RG.Component.CombatMods());
    }
    else {
        RG.err('Actor.Rogue', 'setIsPlayer',
            'Actor cannot be changed from player to mob.');
    }
};

/* Returns the next action for this actor.*/
RG.Actor.Rogue.prototype.nextAction = function(obj) {
    // Use actor brain to determine the action
    var cb = this._brain.decideNextAction(obj);
    var action = null;

    if (cb !== null) {
        const speed = this.getSpeed();
        const duration = parseInt(RG.BASE_SPEED / speed * RG.ACTION_DUR, 10);
        action = new RG.Time.RogueAction(duration, cb, {});
    }
    else {
        action = new RG.Time.RogueAction(0, function() {}, {});
    }

    if (this._brain.hasOwnProperty('energy')) {
        action.energy = this._brain.energy;
    }
    action.actor = this;
    return action;
};

/* Returns the cell where this actor is located at.*/
RG.Actor.Rogue.prototype.getCell = function() {
    var x = this.getX();
    var y = this.getY();
    return this.getLevel().getMap().getCell(x, y);
};

RG.Actor.Rogue.prototype.toJSON = function() {
    var obj = {
        name: this.getName(),
        type: this.getType(),
        components: {
            Combat: this.get('Combat').toJSON(),
            Experience: this.get('Experience').toJSON(),
            Health: this.get('Health').toJSON(),
            Stats: this.get('Stats').toJSON()
        },
        inventory: this.getInvEq().getInventory().toJSON(),
        equipment: this.getInvEq().getEquipment().toJSON()
    };

    if (this.has('Hunger')) {
        obj.components.Hunger = this.get('Hunger').toJSON();
    }

    return obj;
};

//---------------------------------
// Combat-related methods
//---------------------------------

RG.Actor.Rogue.prototype.getAttack = function() {
    var attack = this.get('Combat').getAttack();
    attack += this.getEquipAttack();

    if (this.has('CombatMods')) {
        attack += this.get('CombatMods').getAttack();
    }

    attack += Math.floor(this.getAccuracy() / 2);
    return attack;
};

RG.Actor.Rogue.prototype.getDefense = function() {
    var defense = this.get('Combat').getDefense();
    defense += this.getEquipDefense();
    if (this.has('CombatMods')) {
        defense += this.get('CombatMods').getDefense();
    }
    defense += Math.floor(this.getAgility() / 2);
    return defense;
};

RG.Actor.Rogue.prototype.getProtection = function() {
    var protection = this.get('Combat').getProtection();
    protection += this.getEquipProtection();
    if (this.has('CombatMods')) {
        protection += this.get('CombatMods').getProtection();
    }
    return protection;
};

RG.Actor.Rogue.prototype.getDamage = function() {
    var damage = this.get('Combat').getDamage();
    var strength = this.getStrength();
    strength += this.getInvEq().getEquipment().getStrength();
    damage += RG.strengthToDamage(strength);
    if (this.has('CombatMods')) {damage += this.get('CombatMods').getDamage();}
    return damage;

};

//-------------------------------------------------------------
// Stats-related methods (these take eq and boosts into account
//-------------------------------------------------------------

RG.Actor.Rogue.prototype.getAccuracy = function() {
    var acc = this.get('Stats').getAccuracy();
    acc += this.getInvEq().getEquipment().getAccuracy();
    if (this.has('StatsMods')) {acc += this.get('StatsMods').getAccuracy();}
    return acc;
};

RG.Actor.Rogue.prototype.getAgility = function() {
    var agi = this.get('Stats').getAgility();
    agi += this.getInvEq().getEquipment().getAgility();
    if (this.has('StatsMods')) {agi += this.get('StatsMods').getAgility();}
    return agi;
};

RG.Actor.Rogue.prototype.getStrength = function() {
    var str = this.get('Stats').getStrength();
    str += this.getInvEq().getEquipment().getStrength();
    if (this.has('StatsMods')) {str += this.get('StatsMods').getStrength();}
    return str;
};

RG.Actor.Rogue.prototype.getWillpower = function() {
    var wil = this.get('Stats').getWillpower();
    wil += this.getInvEq().getEquipment().getWillpower();
    if (this.has('StatsMods')) {wil += this.get('StatsMods').getWillpower();}
    return wil;
};

RG.Actor.Rogue.prototype.getSpeed = function() {
    var speed = this.get('Stats').getSpeed();
    speed += this.getInvEq().getEquipment().getSpeed();
    if (this.has('StatsMods')) {speed += this.get('StatsMods').getSpeed();}
    return speed;

};

/* Spirit actors. They have Ethereal component and cannot be attacked, but they
 * can be captured by SpiritGem-objects.*/
RG.Actor.Spirit = function(name) {
    RG.Actor.Rogue.call(this, name);
    this.setType('spirit');

    this.add('Ethereal', new RG.Component.Ethereal());

    const spiritBrain = new RG.Brain.Spirit(this);
    this.setBrain(spiritBrain);

};
RG.extend2(RG.Actor.Spirit, RG.Actor.Rogue);

module.exports = RG.Actor;
<commit_msg>Changed const->var/let.<commit_after>
const RG = require('./rg.js');

RG.Object = require('./object.js');
RG.Component = require('./component.js');
RG.Brain = require('./brain.js');
RG.Inv = require('./inv.js');

RG.Actor = {};

/* Object representing a game actor who takes actions.  */
RG.Actor.Rogue = function(name) { // {{{2
    RG.Object.Locatable.call(this);
    RG.Entity.call(this);
    this.setPropType('actors');

    // Member vars
    this._brain = new RG.Brain.Rogue(this);
    this._brain.getMemory().addEnemyType('player');

    let _name = name;
    this._isPlayer = false;
    let _fovRange = RG.FOV_RANGE;

    this._invEq = new RG.Inv.Inventory(this);
    this._maxWeight = 10.0;

    // Components for this entity
    this.add('Action', new RG.Component.Action());
    this.add('Experience', new RG.Component.Experience());
    this.add('Combat', new RG.Component.Combat());
    this.add('Stats', new RG.Component.Stats());
    this.add('Health', new RG.Component.Health(50));

    this.setName = function(name) {_name = name;};
    this.getName = function() {return _name;};

    /* Returns true if actor is a player.*/
    this.isPlayer = function() {return this._isPlayer;};

    this.getFOVRange = function() { return _fovRange;};
    this.setFOVRange = function(range) {_fovRange = range;};

    //---------------------------------
    // Brain-relatd methods
    //---------------------------------

    this.addEnemy = function(actor) {this._brain.addEnemy(actor);};

    this.isEnemy = function(actor) {
        return this._brain.getMemory().isEnemy(actor);
    };

    this.getBrain = function() {return this._brain;};

    this.setBrain = function(brain) {
        this._brain = brain;
        this._brain.setActor(this);
    };

    //---------------------------------
    // Equipment related methods
    //---------------------------------

    this.getInvEq = function() { return this._invEq; };

    /* Returns weapon that is wielded by the actor.*/
    this.getWeapon = function() {return this._invEq.getWeapon();};

    /* Returns missile equipped by the player.*/
    this.getMissile = function() {
        return this._invEq.getEquipment().getItem('missile');
    };

    this.getEquipAttack = function() {
        return this._invEq.getEquipment().getAttack();
    };

    this.getEquipDefense = function() {
        return this._invEq.getEquipment().getDefense();
    };

    this.getEquipProtection = function() {
        return this._invEq.getEquipment().getProtection();
    };

};
RG.extend2(RG.Actor.Rogue, RG.Object.Locatable);
RG.extend2(RG.Actor.Rogue, RG.Entity);

/* Returns carrying capacity of the actor.*/
RG.Actor.Rogue.prototype.getMaxWeight = function() {
    const statStr = this.get('Stats').getStrength();
    const eqStr = this._invEq.getEquipment().getStrength();
    return 2 * statStr + 2 * eqStr + this._maxWeight;
};

/* Marks actor as player. Cannot unset player.*/
RG.Actor.Rogue.prototype.setIsPlayer = function(isPlayer) {
    if (isPlayer) {
        this._isPlayer = isPlayer;
        this._brain = new RG.Brain.Player(this);
        this.setType('player');
        this.add('StatsMods', new RG.Component.StatsMods());
        this.add('CombatMods', new RG.Component.CombatMods());
    }
    else {
        RG.err('Actor.Rogue', 'setIsPlayer',
            'Actor cannot be changed from player to mob.');
    }
};

/* Returns the next action for this actor.*/
RG.Actor.Rogue.prototype.nextAction = function(obj) {
    // Use actor brain to determine the action
    const cb = this._brain.decideNextAction(obj);
    let action = null;

    if (cb !== null) {
        const speed = this.getSpeed();
        const duration = parseInt(RG.BASE_SPEED / speed * RG.ACTION_DUR, 10);
        action = new RG.Time.RogueAction(duration, cb, {});
    }
    else {
        action = new RG.Time.RogueAction(0, function() {}, {});
    }

    if (this._brain.hasOwnProperty('energy')) {
        action.energy = this._brain.energy;
    }
    action.actor = this;
    return action;
};

/* Returns the cell where this actor is located at.*/
RG.Actor.Rogue.prototype.getCell = function() {
    const x = this.getX();
    const y = this.getY();
    return this.getLevel().getMap().getCell(x, y);
};

RG.Actor.Rogue.prototype.toJSON = function() {
    const obj = {
        name: this.getName(),
        type: this.getType(),
        components: {
            Combat: this.get('Combat').toJSON(),
            Experience: this.get('Experience').toJSON(),
            Health: this.get('Health').toJSON(),
            Stats: this.get('Stats').toJSON()
        },
        inventory: this.getInvEq().getInventory().toJSON(),
        equipment: this.getInvEq().getEquipment().toJSON()
    };

    if (this.has('Hunger')) {
        obj.components.Hunger = this.get('Hunger').toJSON();
    }

    return obj;
};

//---------------------------------
// Combat-related methods
//---------------------------------

RG.Actor.Rogue.prototype.getAttack = function() {
    let attack = this.get('Combat').getAttack();
    attack += this.getEquipAttack();

    if (this.has('CombatMods')) {
        attack += this.get('CombatMods').getAttack();
    }

    attack += Math.floor(this.getAccuracy() / 2);
    return attack;
};

RG.Actor.Rogue.prototype.getDefense = function() {
    let defense = this.get('Combat').getDefense();
    defense += this.getEquipDefense();
    if (this.has('CombatMods')) {
        defense += this.get('CombatMods').getDefense();
    }
    defense += Math.floor(this.getAgility() / 2);
    return defense;
};

RG.Actor.Rogue.prototype.getProtection = function() {
    let protection = this.get('Combat').getProtection();
    protection += this.getEquipProtection();
    if (this.has('CombatMods')) {
        protection += this.get('CombatMods').getProtection();
    }
    return protection;
};

RG.Actor.Rogue.prototype.getDamage = function() {
    let damage = this.get('Combat').getDamage();
    let strength = this.getStrength();
    strength += this.getInvEq().getEquipment().getStrength();
    damage += RG.strengthToDamage(strength);
    if (this.has('CombatMods')) {damage += this.get('CombatMods').getDamage();}
    return damage;

};

//-------------------------------------------------------------
// Stats-related methods (these take eq and boosts into account
//-------------------------------------------------------------

RG.Actor.Rogue.prototype.getAccuracy = function() {
    let acc = this.get('Stats').getAccuracy();
    acc += this.getInvEq().getEquipment().getAccuracy();
    if (this.has('StatsMods')) {acc += this.get('StatsMods').getAccuracy();}
    return acc;
};

RG.Actor.Rogue.prototype.getAgility = function() {
    let agi = this.get('Stats').getAgility();
    agi += this.getInvEq().getEquipment().getAgility();
    if (this.has('StatsMods')) {agi += this.get('StatsMods').getAgility();}
    return agi;
};

RG.Actor.Rogue.prototype.getStrength = function() {
    let str = this.get('Stats').getStrength();
    str += this.getInvEq().getEquipment().getStrength();
    if (this.has('StatsMods')) {str += this.get('StatsMods').getStrength();}
    return str;
};

RG.Actor.Rogue.prototype.getWillpower = function() {
    let wil = this.get('Stats').getWillpower();
    wil += this.getInvEq().getEquipment().getWillpower();
    if (this.has('StatsMods')) {wil += this.get('StatsMods').getWillpower();}
    return wil;
};

RG.Actor.Rogue.prototype.getSpeed = function() {
    let speed = this.get('Stats').getSpeed();
    speed += this.getInvEq().getEquipment().getSpeed();
    if (this.has('StatsMods')) {speed += this.get('StatsMods').getSpeed();}
    return speed;

};

/* Spirit actors. They have Ethereal component and cannot be attacked, but they
 * can be captured by SpiritGem-objects.*/
RG.Actor.Spirit = function(name) {
    RG.Actor.Rogue.call(this, name);
    this.setType('spirit');

    this.add('Ethereal', new RG.Component.Ethereal());

    const spiritBrain = new RG.Brain.Spirit(this);
    this.setBrain(spiritBrain);

};
RG.extend2(RG.Actor.Spirit, RG.Actor.Rogue);

module.exports = RG.Actor;
<|endoftext|>


<commit_before>import React from 'react';
import {
    StyleSheet,
    View,
    Slider,
    Text,
    TouchableOpacity,
    DeviceEventEmitter,
    ActivityIndicator,
    AsyncStorage,
    BackHandler,
    Alert,
    NativeModules
} from 'react-native';
import RNAudioStreamer from 'react-native-audio-streamer';
import MusicControl from 'react-native-music-control';
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons';
import RNExitApp from 'react-native-exit-app';
const { AudioFocusManager }  = NativeModules;

const statusMap = {
    PLAYING: MusicControl.STATE_PLAYING,
    PAUSED: MusicControl.STATE_PAUSED,
    BUFFERING: MusicControl.STATE_BUFFERING
};

const defaultState = {
    status: 'STOPPED',
    nowPlaying: '',
    duration: 0,
    currTime: 0
};

const PINK = '#E91E63';

export default class Player extends React.Component {
    state = defaultState;

    constructor(props) {
        super(props);
    }

    componentDidMount() {
        DeviceEventEmitter.addListener('RNAudioStreamerStatusChanged', this._audioStatus.bind(this));
        DeviceEventEmitter.addListener('WiredHeadset', this._headphonePlugged.bind(this));
        DeviceEventEmitter.addListener('onAudioFocusChange', this._audioFocusChanged.bind(this));
        BackHandler.addEventListener('hardwareBackPress', this._backPressed.bind(this));
        MusicControl.enableControl('play', true);
        MusicControl.enableControl('pause', true);
        MusicControl.enableBackgroundMode(true);
        MusicControl.enableControl('closeNotification', true, {when: 'always'});
        MusicControl.on('play', ()=> {
            RNAudioStreamer.play();
        });
        MusicControl.on('pause', ()=> {
            RNAudioStreamer.pause();
        });
        MusicControl.on('closeNotification', async ()=> {
            await this._saveStateAndExit();
        });
        this._checkSavedStateAndLoad();
    }

    componentWillUnmount() {
        if (this.timeInterval) {
            clearInterval(this.timeInterval);
        }
    }

    async _saveStateAndExit() {
        RNAudioStreamer.setUrl('');
        await AsyncStorage.setItem('saved', JSON.stringify(this.segment));
        MusicControl.resetNowPlaying();
        RNExitApp.exitApp();
    }

    _backPressed() {
        if (this.state.status === 'PLAYING') {
            Alert.alert(
                'בטוח לצאת?',
                'יציאה תפסיק את הנגינה',
                [
                    {text: 'בטל', onPress: () => {}},
                    {text: 'צא', onPress: () => {
                        this._saveStateAndExit();
                    }}
                ]
            );
        } else {
            this._saveStateAndExit();
        }

        return true;
    }

    async _checkSavedStateAndLoad() {
        let savedSegemnt = await AsyncStorage.getItem('saved');
        if (savedSegemnt) {
            savedSegemnt = JSON.parse(savedSegemnt);
            console.log('found saved state!!! ', savedSegemnt);
            this.playSegment(savedSegemnt);
            RNAudioStreamer.pause();
            let currTime = Math.max(0, savedSegemnt.currTime - 5);
            RNAudioStreamer.seekToTime(currTime);
            this.setState({
                currTime: currTime,
                duration: savedSegemnt.duration
            });
        }
    }

    _headphonePlugged(data) {
        if (this.state.status === 'PLAYING' && !data.isPlugged) {
            RNAudioStreamer.pause();
        }
    }

    _audioFocusChanged(data) {
        console.log('_audioFocusChanged: ', data);
        if (this.state.status === 'PLAYING' && !data.inFocus) {
            RNAudioStreamer.pause();
            this.pausedFromFocusLoss = true;
        } else if (this.state.status === 'PAUSED' && data.inFocus && this.pausedFromFocusLoss) {
            RNAudioStreamer.play();
            this.pausedFromFocusLoss = false;
        }
    }

    _audioStatus(status) {
        console.log(status);
        this.setState({status});
        if (status === 'PLAYING') {
            RNAudioStreamer.duration((err, duration) => {
                console.log(duration);
                this.setState({duration});
                this.segment.duration = duration;
            })
        }
        MusicControl.updatePlayback({
            state: statusMap[status]
        });
    }

    playSegment(segment) {
        if (this.timeInterval) {
            clearInterval(this.timeInterval);
        }
        this.segment = segment;
        RNAudioStreamer.setUrl(segment.url);
        this.setState({
            nowPlaying: segment.title,
            currTime: 0
        });
        RNAudioStreamer.play();
        MusicControl.setNowPlaying({
            title: segment.title,
            artwork: segment.image,
            color: 0xE91E63
        });
        AudioFocusManager.startListening();
        this.timeInterval = setInterval(() => {
            RNAudioStreamer.currentTime((err, currentTime) => {
                if (err) {
                    console.log(err);
                } else {
                    this.segment.currTime = currentTime;
                    if (!this.seeking) {
                        this.setState({currTime: currentTime});
                    }
                }
            })
        }, 1000);
    }

    _playPausePressed() {
        if (this.state.status === 'PLAYING') {
            RNAudioStreamer.pause();
        } else if (this.state.status === 'PAUSED') {
            RNAudioStreamer.play();
        }
    }

    _seekingComplete(value) {
        this.seeking = false;
        RNAudioStreamer.seekToTime(value);
    }

    _seek(value) {
        value = Math.floor(value);
        this.seeking = true;
        this.setState({currTime: value});
    }

    render() {
        let icon = null;
        if (this.state.status === 'PLAYING') {
            icon = <Icon name="pause" size={30} color={PINK}/>;
        } else if (this.state.status === 'PAUSED' || this.state.status === "STANDBY") {
            icon = <Icon name="play" size={30} color={PINK}/>;
        } else if (this.state.status === 'BUFFERING') {
            icon = <ActivityIndicator color={PINK}/>
        }

        return (
            <View style={styles.container}>
                <Text style={styles.title} lineNumber={1}>{this.state.nowPlaying}</Text>
                <View style={styles.playBox}>
                    <TouchableOpacity style={styles.playButton} onPress={this._playPausePressed.bind(this)}>
                        {icon}
                    </TouchableOpacity>
                    <View style={styles.slider}>
                        <Text>{secondsToTime(this.state.currTime)}</Text>
                        <Slider
                            style={{flex: 1}}
                            value={this.state.currTime}
                            maximumValue={this.state.duration}
                            onSlidingComplete={this._seekingComplete.bind(this)}
                            onValueChange={this._seek.bind(this)}
                            minimumTrackTintColor={PINK}
                            maximumTrackTintColor={PINK}
                            thumbTintColor={PINK}
                        />
                        <Text>{secondsToTime(this.state.duration)}</Text>
                    </View>
                </View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        // position: 'absolute',
        height: 100,
        // bottom: 0,
        // right: 0,
        // left: 0,
        elevation: 10,
        backgroundColor: 'white',
        alignItems: 'center',
        justifyContent: 'center',
        paddingHorizontal: 10,
        paddingVertical: 10,
    },
    title: {
        flex: 1
    },
    playBox: {
        height: 50,
        backgroundColor: 'white',
        flexDirection: 'row',
        alignItems: 'center'
    },
    playButton: {
        height: 50,
        width: 50,
        justifyContent: 'center',
        alignItems: 'center'
    },
    slider: {
        flex: 1,
        marginVertical: 10,
        flexDirection: 'row',
        alignItems: 'center'
    }
});

function secondsToTime(seconds) {
    let minutes = Math.floor(seconds / 60);
    let minutesStr = ('0' + minutes).slice(-2);
    seconds = seconds % 60;
    let secondsStr = ('0' + seconds).slice(-2);

    if (minutes / 60 > 1) {
        let hours = Math.floor(minutes / 60);
        minutes = minutes % 60;
        minutesStr = ('0' + minutes).slice(-2);
        return `${hours}:${minutesStr}:${secondsStr}`;
    }

    return `${minutesStr}:${secondsStr}`;
}<commit_msg>batter saved segment experience<commit_after>import React from 'react';
import {
    StyleSheet,
    View,
    Slider,
    Text,
    TouchableOpacity,
    DeviceEventEmitter,
    ActivityIndicator,
    AsyncStorage,
    BackHandler,
    Alert,
    NativeModules
} from 'react-native';
import RNAudioStreamer from 'react-native-audio-streamer';
import MusicControl from 'react-native-music-control';
import Icon from 'react-native-vector-icons/dist/MaterialCommunityIcons';
import RNExitApp from 'react-native-exit-app';
const { AudioFocusManager }  = NativeModules;

const statusMap = {
    PLAYING: MusicControl.STATE_PLAYING,
    PAUSED: MusicControl.STATE_PAUSED,
    BUFFERING: MusicControl.STATE_BUFFERING
};

const defaultState = {
    status: 'STOPPED',
    nowPlaying: '',
    duration: 0,
    currTime: 0
};

const PINK = '#E91E63';

export default class Player extends React.Component {
    state = defaultState;

    constructor(props) {
        super(props);
    }

    componentDidMount() {
        DeviceEventEmitter.addListener('RNAudioStreamerStatusChanged', this._audioStatus.bind(this));
        DeviceEventEmitter.addListener('WiredHeadset', this._headphonePlugged.bind(this));
        DeviceEventEmitter.addListener('onAudioFocusChange', this._audioFocusChanged.bind(this));
        BackHandler.addEventListener('hardwareBackPress', this._backPressed.bind(this));
        MusicControl.enableControl('play', true);
        MusicControl.enableControl('pause', true);
        MusicControl.enableBackgroundMode(true);
        MusicControl.enableControl('closeNotification', true, {when: 'always'});
        MusicControl.on('play', ()=> {
            RNAudioStreamer.play();
        });
        MusicControl.on('pause', ()=> {
            RNAudioStreamer.pause();
        });
        MusicControl.on('closeNotification', async ()=> {
            await this._saveStateAndExit();
        });
        this._checkSavedStateAndLoad();
    }

    componentWillUnmount() {
        if (this.timeInterval) {
            clearInterval(this.timeInterval);
        }
    }

    async _saveStateAndExit() {
        if (this.segment) {
            RNAudioStreamer.setUrl('');
            await AsyncStorage.setItem('saved', JSON.stringify(this.segment));
            MusicControl.resetNowPlaying();
        }
        RNExitApp.exitApp();
    }

    _backPressed() {
        if (this.state.status === 'PLAYING') {
            Alert.alert(
                'בטוח לצאת?',
                'יציאה תפסיק את הנגינה',
                [
                    {text: 'בטל', onPress: () => {}},
                    {text: 'צא', onPress: () => {
                        this._saveStateAndExit();
                    }}
                ]
            );
        } else {
            this._saveStateAndExit();
        }

        return true;
    }

    async _checkSavedStateAndLoad() {
        let savedSegemnt = await AsyncStorage.getItem('saved');
        if (savedSegemnt) {
            savedSegemnt = JSON.parse(savedSegemnt);
            console.log('found saved state!!! ', savedSegemnt);
            // this.playSegment(savedSegemnt);
            // RNAudioStreamer.pause();
            savedSegemnt.currTime = Math.max(0, savedSegemnt.currTime - 5);
            // RNAudioStreamer.seekToTime(currTime);
            this.savedSagment = savedSegemnt;
            this.setState({
                status: 'STANDBY',
                nowPlaying: savedSegemnt.title,
                currTime: savedSegemnt.currTime,
                duration: savedSegemnt.duration
            });
        }
    }

    _headphonePlugged(data) {
        if (this.state.status === 'PLAYING' && !data.isPlugged) {
            RNAudioStreamer.pause();
        }
    }

    _audioFocusChanged(data) {
        console.log('_audioFocusChanged: ', data);
        if (this.state.status === 'PLAYING' && !data.inFocus) {
            RNAudioStreamer.pause();
            this.pausedFromFocusLoss = true;
        } else if (this.state.status === 'PAUSED' && data.inFocus && this.pausedFromFocusLoss) {
            RNAudioStreamer.play();
            this.pausedFromFocusLoss = false;
        }
    }

    _audioStatus(status) {
        console.log(status);
        this.setState({status});
        if (status === 'PLAYING') {
            RNAudioStreamer.duration((err, duration) => {
                console.log(duration);
                this.setState({duration});
                this.segment.duration = duration;
            })
        }
        MusicControl.updatePlayback({
            state: statusMap[status]
        });
    }

    playSegment(segment, play = true) {
        if (this.timeInterval) {
            clearInterval(this.timeInterval);
        }
        this.segment = segment;
        RNAudioStreamer.setUrl(segment.url);
        if (play) {
            this.setState({
                nowPlaying: segment.title,
                currTime: 0
            });
            RNAudioStreamer.play();
        }
        MusicControl.setNowPlaying({
            title: segment.title,
            artwork: segment.image,
            color: 0xE91E63
        });
        AudioFocusManager.startListening();
        this.timeInterval = setInterval(() => {
            RNAudioStreamer.currentTime((err, currentTime) => {
                if (err) {
                    console.log(err);
                } else {
                    this.segment.currTime = currentTime;
                    if (!this.seeking) {
                        this.setState({currTime: currentTime});
                    }
                }
            })
        }, 1000);
    }

    _playPausePressed() {
        if (this.state.status === 'PLAYING') {
            RNAudioStreamer.pause();
        } else if (this.state.status === 'PAUSED') {
            RNAudioStreamer.play();
        } else if (this.state.status === 'STANDBY') {
            this.playSegment(this.savedSagment, false);
            RNAudioStreamer.seekToTime(this.savedSagment.currTime);
            RNAudioStreamer.play();
        }
    }

    _seekingComplete(value) {
        this.seeking = false;
        RNAudioStreamer.seekToTime(value);
    }

    _seek(value) {
        value = Math.floor(value);
        this.seeking = true;
        this.setState({currTime: value});
    }

    render() {
        let icon = null;
        if (this.state.status === 'PLAYING') {
            icon = <Icon name="pause" size={30} color={PINK}/>;
        } else if (this.state.status === 'PAUSED' || this.state.status === "STANDBY") {
            icon = <Icon name="play" size={30} color={PINK}/>;
        } else if (this.state.status === 'BUFFERING') {
            icon = <ActivityIndicator color={PINK}/>
        }

        return (
            <View style={styles.container}>
                <Text style={styles.title} lineNumber={1}>{this.state.nowPlaying}</Text>
                <View style={styles.playBox}>
                    <TouchableOpacity style={styles.playButton} onPress={this._playPausePressed.bind(this)}>
                        {icon}
                    </TouchableOpacity>
                    <View style={styles.slider}>
                        <Text>{secondsToTime(this.state.currTime)}</Text>
                        <Slider
                            style={{flex: 1}}
                            value={this.state.currTime}
                            maximumValue={this.state.duration}
                            onSlidingComplete={this._seekingComplete.bind(this)}
                            onValueChange={this._seek.bind(this)}
                            minimumTrackTintColor={PINK}
                            maximumTrackTintColor={PINK}
                            thumbTintColor={PINK}
                        />
                        <Text>{secondsToTime(this.state.duration)}</Text>
                    </View>
                </View>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    container: {
        // position: 'absolute',
        height: 100,
        // bottom: 0,
        // right: 0,
        // left: 0,
        elevation: 10,
        backgroundColor: 'white',
        alignItems: 'center',
        justifyContent: 'center',
        paddingHorizontal: 10,
        paddingVertical: 10,
    },
    title: {
        flex: 1
    },
    playBox: {
        height: 50,
        backgroundColor: 'white',
        flexDirection: 'row',
        alignItems: 'center'
    },
    playButton: {
        height: 50,
        width: 50,
        justifyContent: 'center',
        alignItems: 'center'
    },
    slider: {
        flex: 1,
        marginVertical: 10,
        flexDirection: 'row',
        alignItems: 'center'
    }
});

function secondsToTime(seconds) {
    let minutes = Math.floor(seconds / 60);
    let minutesStr = ('0' + minutes).slice(-2);
    seconds = seconds % 60;
    let secondsStr = ('0' + seconds).slice(-2);

    if (minutes / 60 > 1) {
        let hours = Math.floor(minutes / 60);
        minutes = minutes % 60;
        minutesStr = ('0' + minutes).slice(-2);
        return `${hours}:${minutesStr}:${secondsStr}`;
    }

    return `${minutesStr}:${secondsStr}`;
}<|endoftext|>


<commit_before><commit_msg>show also query parameters<commit_after><|endoftext|>


<commit_before>import Stats from 'util/stats.min'
import { queue,EventEmitter } from 'util/_'

//资源加载
class Loader {
    constructor(arr) {
        this._images = {};
        this.task = [];
    }
    //加载图片
    load(arr,callback) {
        let self = this;
        for(let i = 0;i<arr.length;i++) {
            if( i == arr.length - 1 ){
                self.task.push(function(){
                    self._images[arr[i]] = new Image();
                    self._images[arr[i]].onload = function(){
                        callback();
                        return
                    }
                    self._images[arr[i]].src = arr[i];
                })
            } else {
                self.task.push(function(cb){
                    self._images[arr[i]] = new Image();
                    self._images[arr[i]].onload = function(){
                        cb();
                    }
                    self._images[arr[i]].src = arr[i];
                })
            }
        }

        return queue(self.task,this)
    }
    //获取图片
    pick(src) {
        if ( typeof this._images[src] != 'undefined' ){
            return  this._images[src];
        } else {
            throw new Error('请传入图片对象')
        }
    }
}

//舞台
class Stage extends EventEmitter {
    constructor(options) {
        super();
        this.dpr = window.devicePixelRatio || 1;
        //资源列表
        this.assets = options.list || null;
        //dom节点
        this.el = options.el;
        this.context = options.el.getContext('2d');
        //精灵字典
        this.sprites = [];
        //世界地图
        this.map = options.map || null;

        this.init();
    }
    init () {
        //event测试
        //this.on((content) => console.log(`get published content: ${content}`), 'Event test')

        //canvas外层容器宽高 利用css响应布局
        this._width = this.el.parentNode.clientWidth;
        this._height = this.el.parentNode.clientHeight;
        //真实宽高
        this.width = this.dpr * this._width;
        this.height = this.dpr * this._height;
        //初始化canvas元素
        this.el.style.width = `${this._width}px`;
        this.el.style.height = `${this._height}px`;
        this.el.width = ~~ this.width;
        this.el.height = ~~ this.height;
        //初始化loader
        this.im = new Loader(this.assets);

        //加载资源
        this.load();
    }
    dp (px) {
        return ~~ px * this.dpr
    }
    load () {
        //判断是否需要加载资源
        if( this.assets ){

            //加载周期
            this.on(()=>{this.update()},'load');
            //加载回调
            this.im.load(this.assets,()=>{this.emit(console.log('load success'),'load')});

            let loadTxt = 'Loading..';
            let textWidth = ~~ this.context.measureText(loadTxt).width * this.dpr;
            let textHeight =  15*this.dpr;

            let rx = ~~ ( this._width - textWidth ) / 2;
            let ry = ~~ ( this._height - textHeight ) / 2;

            let loadPx = 15;
            this.textAlign="center";
            this.context.font = `400 ${loadPx*this.dpr}px 微软雅黑,Sans-Serif`;

            this.context.fillStyle = '#ccc';

            this.context.fillText(loadTxt,rx*this.dpr,ry*this.dpr);

        } else {
            this.update();
        }

    }
    clear(x = 0, y = 0,width = this.width , height = this.height) {
        this.context.clearRect(x, y, width, height);
    }
    //主loop
    update(type,obj,x,y,rx,ry) {
        //event测试
        //this.emit('pub', 'Event test');

        this.clear();
        //todo MAP
        let t = this.im.pick('../assets/ji.jpg')
        this.context.drawImage(t,0,0,t.width,t.height);
    }
    //收集并重写精灵的行为
    draw() {
        //update type:text,filltext;image,drawImage 封装常用方法 保留坐标到this.store
    }
    //map
    //添加精灵元素
    addSprite (name,sprite) {
        this.sprites[name]=sprite;
    }
    //移除精灵元素
    removeSprite (name) {
        if ( this.sprites[name] ){
            delete this.sprites[name];
        }
    }
}

//精灵类
class Sprite {
    constructor (){

    }
}

const stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
//stats.update()

window.onload = function(){
    new Stage({
        el:document.querySelector('#stage'),
        list:['../assets/ji.jpg']
    },function(){
        console.log('su!!')
    });
}

window.addEventListener('resize', () => {
    // s.init();
    // s.load(true);
});

if (module.hot) module.hot.accept();
<commit_msg>update<commit_after>import Stats from 'util/stats.min'
import { queue,EventEmitter } from 'util/_'

//资源加载
class Loader {
    constructor(arr) {
        this._images = {};
        this.task = [];
    }
    //加载图片
    load(arr,callback) {
        let self = this;
        for(let i = 0;i<arr.length;i++) {
            if( i == arr.length - 1 ){
                self.task.push(function(){
                    self._images[arr[i]] = new Image();
                    self._images[arr[i]].onload = function(){
                        callback();
                        return
                    }
                    self._images[arr[i]].src = arr[i];
                })
            } else {
                self.task.push(function(cb){
                    self._images[arr[i]] = new Image();
                    self._images[arr[i]].onload = function(){
                        cb();
                    }
                    self._images[arr[i]].src = arr[i];
                })
            }
        }

        return queue(self.task,this)
    }
    //获取图片
    pick(src) {
        if ( typeof this._images[src] != 'undefined' ){
            return  this._images[src];
        } else {
            throw new Error('请传入图片对象')
        }
    }
}

//舞台
class Stage extends EventEmitter {
    constructor(options) {
        super();
        this.dpr = window.devicePixelRatio || 1;
        //资源列表
        this.assets = options.list || null;
        //dom节点
        this.el = options.el;
        this.context = options.el.getContext('2d');
        //精灵字典
        this.sprites = [];
        //世界地图
        this.map = options.map || null;

        this.init();
    }
    init () {
        //event测试
        //this.on((content) => console.log(`get published content: ${content}`), 'Event test')

        //canvas外层容器宽高 利用css响应布局
        this._width = this.el.parentNode.clientWidth;
        this._height = this.el.parentNode.clientHeight;
        //真实宽高
        this.width = this.dpr * this._width;
        this.height = this.dpr * this._height;
        //初始化canvas元素
        this.el.style.width = `${this._width}px`;
        this.el.style.height = `${this._height}px`;
        this.el.width = ~~ this.width;
        this.el.height = ~~ this.height;
        //初始化loader
        this.im = new Loader(this.assets);

        //加载资源
        this.load();
    }
    dp (px) {
        return ~~ px * this.dpr
    }
    load () {
        //判断是否需要加载资源
        if( this.assets ){

            //加载周期
            this.on(()=>{this.update()},'load');
            //加载回调
            this.im.load(this.assets,()=>{this.emit(console.log('load success'),'load')});

            let loadTxt = 'Loading..';
            let textWidth = ~~ this.context.measureText(loadTxt).width * this.dpr;
            let textHeight =  15*this.dpr;

            let rx = ~~ ( this._width - textWidth ) / 2;
            let ry = ~~ ( this._height - textHeight ) / 2;

            let loadPx = 14;
            this.textAlign="center";
            //this.context.font = `400 ${loadPx*this.dpr}px 微软雅黑,Sans-Serif`;
            this.context.font = `normal small-caps 400 ${loadPx*this.dpr}px 'Lato', sans-serif`;

            this.context.fillStyle = '#ccc';

            this.context.fillText(loadTxt,rx*this.dpr,ry*this.dpr);

        } else {
            this.update();
        }

    }
    clear(x = 0, y = 0,width = this.width , height = this.height) {
        this.context.clearRect(x, y, width, height);
    }
    //主loop
    update(type,obj,x,y,rx,ry) {
        //event测试
        //this.emit('pub', 'Event test');

        this.clear();
        //todo MAP
        let t = this.im.pick('../assets/ji.jpg')
        this.context.drawImage(t,0,0,t.width,t.height);
    }
    //收集并重写精灵的行为
    draw() {
        //update type:text,filltext;image,drawImage 封装常用方法 保留坐标到this.store
    }
    //map
    //添加精灵元素
    addSprite (name,sprite) {
        this.sprites[name]=sprite;
    }
    //移除精灵元素
    removeSprite (name) {
        if ( this.sprites[name] ){
            delete this.sprites[name];
        }
    }
}

//精灵类
class Sprite {
    constructor (){

    }
}

const stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.right = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild( stats.domElement );
//stats.update()

window.onload = function(){
    new Stage({
        el:document.querySelector('#stage'),
        list:['../assets/ji.jpg']
    },function(){
        console.log('su!!')
    });
}

window.addEventListener('resize', () => {
    // s.init();
    // s.load(true);
});

if (module.hot) module.hot.accept();
<|endoftext|>


<commit_before>angular.module('scavengerApp')
  .controller('storyCtrl', ['$scope', '$rootScope', '$state', '$http', 'ListService', function($scope, $rootScope, $state, $http, ListService) {

    $scope.loaded = false;
    $scope.clues = {};

    var cluesList = ListService;
    var list = ListService;

    cluesList.http({fn: "getEntities", entityName: "Clue"},
      function (response) {
          cluesList.setList(response);
          $scope.clues = cluesList.getList();
      },
      function(response){
        console.log(response);
      });

    list.http({fn: "getEntities", entityName: "Story"},
      function (response) {
          list.setList(response);
          $scope.loaded = true;
          $scope.storyList = list.getList();
      },
      function(response){
        console.log(response);
      });

    $scope.storyCtrlFormData = {id : "-1", name : "", description : "", clueid: "-1", code: "", maxUsers: "-1", end: "", hint: ""};

    $scope.storyCtrlFormData.submit = function(item, event) {
      var data = {fn: "aestory",
       id : $scope.storyCtrlFormData.id,
       name : $scope.storyCtrlFormData.name,
       description : $scope.storyCtrlFormData.description,
       clueid: $scope.storyCtrlFormData.clueid,
       code: $scope.storyCtrlFormData.code,
       maxUsers: $scope.storyCtrlFormData.maxUsers,
       end: $scope.storyCtrlFormData.end,
       hint: $scope.storyCtrlFormData.hint}

      list.http(data,
          function (response) {
            data.id = response.id;
            $scope.storyList[data.id] = data;
          },
          function(response){
            console.log(response);
          });

      $scope.storyCtrlFormData.reset();
    }

     $scope.storyCtrlFormData.reset = function() {
      $scope.storyCtrlFormData.id = -1;
      $scope.storyCtrlFormData.name = "";
      $scope.storyCtrlFormData.description = "";
      $scope.storyCtrlFormData.clueid = -1;
      $scope.storyCtrlFormData.code = "";
      $scope.storyCtrlFormData.maxUsers = -1;
      $scope.storyCtrlFormData.end = "";
      $scope.storyCtrlFormData.hint = "";
     }

     $scope.editItem = function(item) {
      $scope.storyCtrlFormData.id = item.id;
      $scope.storyCtrlFormData.name = item.name;
      $scope.storyCtrlFormData.description = item.description;
      $scope.storyCtrlFormData.clueid = item.clueid;
      $scope.storyCtrlFormData.code = item.code;
      $scope.storyCtrlFormData.maxUsers = item.maxUsers;
      $scope.storyCtrlFormData.end = item.end;
      $scope.storyCtrlFormData.hint = item.end;
     }

    $scope.deleteItem = function(item) {
      var data = {fn: 'deleteEntity', id : item.id, entityName: "Story"};

      list.http(data,
          function (response) {
            delete $scope.storyList[item.id];
          },
          function(response){
            console.log(response);
          });
    };

    $scope.changeState = function(stateName, item) {
      $state.go(stateName, {"storyid": item.id, "story": item});
    };
}]).filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });
    return array;
 }
});

<commit_msg>Fixed hint ui<commit_after>angular.module('scavengerApp')
  .controller('storyCtrl', ['$scope', '$rootScope', '$state', '$http', 'ListService', function($scope, $rootScope, $state, $http, ListService) {

    $scope.loaded = false;
    $scope.clues = {};

    var cluesList = ListService;
    var list = ListService;

    cluesList.http({fn: "getEntities", entityName: "Clue"},
      function (response) {
          cluesList.setList(response);
          $scope.clues = cluesList.getList();
      },
      function(response){
        console.log(response);
      });

    list.http({fn: "getEntities", entityName: "Story"},
      function (response) {
          list.setList(response);
          $scope.loaded = true;
          $scope.storyList = list.getList();
      },
      function(response){
        console.log(response);
      });

    $scope.storyCtrlFormData = {id : "-1", name : "", description : "", clueid: "-1", code: "", maxUsers: "-1", end: "", hint: ""};

    $scope.storyCtrlFormData.submit = function(item, event) {
      var data = {fn: "aestory",
       id : $scope.storyCtrlFormData.id,
       name : $scope.storyCtrlFormData.name,
       description : $scope.storyCtrlFormData.description,
       clueid: $scope.storyCtrlFormData.clueid,
       code: $scope.storyCtrlFormData.code,
       maxUsers: $scope.storyCtrlFormData.maxUsers,
       end: $scope.storyCtrlFormData.end,
       hint: $scope.storyCtrlFormData.hint}

      list.http(data,
          function (response) {
            data.id = response.id;
            $scope.storyList[data.id] = data;
          },
          function(response){
            console.log(response);
          });

      $scope.storyCtrlFormData.reset();
    }

     $scope.storyCtrlFormData.reset = function() {
      $scope.storyCtrlFormData.id = -1;
      $scope.storyCtrlFormData.name = "";
      $scope.storyCtrlFormData.description = "";
      $scope.storyCtrlFormData.clueid = -1;
      $scope.storyCtrlFormData.code = "";
      $scope.storyCtrlFormData.maxUsers = -1;
      $scope.storyCtrlFormData.end = "";
      $scope.storyCtrlFormData.hint = "";
     }

     $scope.editItem = function(item) {
      $scope.storyCtrlFormData.id = item.id;
      $scope.storyCtrlFormData.name = item.name;
      $scope.storyCtrlFormData.description = item.description;
      $scope.storyCtrlFormData.clueid = item.clueid;
      $scope.storyCtrlFormData.code = item.code;
      $scope.storyCtrlFormData.maxUsers = item.maxUsers;
      $scope.storyCtrlFormData.end = item.end;
      $scope.storyCtrlFormData.hint = item.hint;
     }

    $scope.deleteItem = function(item) {
      var data = {fn: 'deleteEntity', id : item.id, entityName: "Story"};

      list.http(data,
          function (response) {
            delete $scope.storyList[item.id];
          },
          function(response){
            console.log(response);
          });
    };

    $scope.changeState = function(stateName, item) {
      $state.go(stateName, {"storyid": item.id, "story": item});
    };
}]).filter('orderObjectBy', function(){
 return function(input, attribute) {
    if (!angular.isObject(input)) return input;

    var array = [];
    for(var objectKey in input) {
        array.push(input[objectKey]);
    }

    array.sort(function(a, b){
        a = parseInt(a[attribute]);
        b = parseInt(b[attribute]);
        return a - b;
    });
    return array;
 }
});

<|endoftext|>


<commit_before>import config from '../config.json';
import {autoDetectRenderer, Container, Point} from 'pixi.js';
import {Entity} from './entity';
import {Key} from './input';
import uuid from 'uuid';
import EntityService from './EntityService';
import MapService from './MapService';
import Radar from './Radar';

let name = 'top-down-arena-shooter';
let version = '0.0.1';
document.title = `${name} v${version}`;
document.body.style.backgroundColor = '#111111';
document.body.style.padding = 0;
document.body.style.margin = 0;

let renderer = autoDetectRenderer(config.width, config.height);
document.body.appendChild(renderer.view);
renderer.view.style.borderColor = '#222222';
renderer.view.style.borderStyle = 'solid';
renderer.view.style.borderWidth = '1px';

let stage = new Container();
let entityService = EntityService.get();
let mapService = MapService.get();
let radar = new Radar();

const getOrCreateSessionID = () => {
  if (!sessionStorage.sessionID) {
    sessionStorage.sessionID = uuid();
  }

  return sessionStorage.sessionID;
};

const handleInitializeEvent = (eventData) => {
  // input: id,x,y,r|...
  stage.removeChildren();
  entityService.clear();
  eventData = eventData.split('|');
  eventData.forEach(entityData => {
    let properties = entityData.split(',');
    let id = properties[0];
    let type = properties[1];
    let x = parseFloat(properties[2]);
    let y = parseFloat(properties[3]);
    let r = parseFloat(properties[4]);
    let w = parseFloat(properties[5]);
    let h = parseFloat(properties[6]);
    let entity = new Entity(id, type, x, y, r, w, h);
    stage.addChild(entity.sprite);
    entityService.add(entity);
  });
};

const handleMapEvent = (eventData) => {
  // input width,height
  let dimensions = eventData.split(',');
  mapService.setDimensions(dimensions[0], dimensions[1]);
};

const handleIdentityEvent = (eventData) => {
  // input: id
  entityService.setPlayerIdentity(eventData);
};

const handleAddEvent = (eventData) => {
  // input: id,x,y,r
  let properties = eventData.split(',');
  let id = properties[0];
  let type = properties[1];
  let x = parseFloat(properties[2]);
  let y = parseFloat(properties[3]);
  let r = parseFloat(properties[4]);
  let w = parseFloat(properties[5]);
  let h = parseFloat(properties[6]);
  let entity = new Entity(id, type, x, y, r, w, h);
  stage.addChild(entity.sprite);
  entityService.add(entity);
};

const handleUpdateEvent = (eventData) => {
  // input: id,x,y,r|...
  eventData = eventData.split('|');
  eventData.forEach(entityData => {
    let properties = entityData.split(',');
    let id = properties[0];
    let entity = entityService.getById(id);
    if (entity) {
      let x = parseFloat(properties[2]);
      let y = parseFloat(properties[3]);
      let r = parseFloat(properties[4]);
      let w = parseFloat(properties[5]);
      let h = parseFloat(properties[6]);
      entity.setPosition(x, y);
      entity.setRotation(r);
      entity.setSize(w, h);
    } else {
      console.log(`can't find entity: ${id}`);
    }
  });
};

const handleRemoveEvent = (eventData) => {
  // input: id
  let entity = entityService.removeById(eventData);
  if (entity) {
    stage.removeChild(entity.sprite);
  }
};

const getEventHandler = (name) => {
  switch (name) {
    case 'initialize': return handleInitializeEvent;
    case 'map': return handleMapEvent;
    case 'identity': return handleIdentityEvent;
    case 'add': return handleAddEvent;
    case 'update': return handleUpdateEvent;
    case 'remove': return handleRemoveEvent;
  }
};

let sessionID = getOrCreateSessionID();

const socket = new WebSocket(`ws://${config.server}/${sessionID}`);

socket.addEventListener('open', (event) => {
  console.log('websocket opened:', config.server);
});

socket.addEventListener('message', (event) => {
  console.log('websocket message received:', event.data);
  let split = event.data.indexOf('|');
  if (split !== -1) {
    let command = event.data.slice(0, split);
    let parameters = event.data.slice(split + 1);
    let eventHandler = getEventHandler(command);
    eventHandler(parameters);
  }
});

socket.addEventListener('close', (event) => {
  console.log('websocket closed:', config.server);
});

let keysDown = [];

window.addEventListener('keydown', (event) => {
  // console.log('keydown:', event.keyCode);
  if (keysDown.includes(event.keyCode)) return;
  keysDown.push(event.keyCode);

  if (event.keyCode === Key.A || event.keyCode === Key.Left) {
    socket.send(`start-rotate|left`);
  }

  if (event.keyCode === Key.D || event.keyCode === Key.Right) {
    socket.send(`start-rotate|right`);
  }

  if (event.keyCode === Key.W || event.keyCode === Key.Up) {
    socket.send(`start-thrust|forward`);
  }

  if (event.keyCode === Key.S || event.keyCode === Key.Down) {
    socket.send(`start-thrust|backward`);
  }
});

window.addEventListener('keyup', (event) => {
  // console.log('keyup:', event.keyCode);
  let index = keysDown.indexOf(event.keyCode);
  if (index !== -1) {
    keysDown.splice(index, 1);
  }

  if (event.keyCode === Key.A || event.keyCode === Key.Left) {
    socket.send(`stop-rotate|left`);
  }

  if (event.keyCode === Key.D || event.keyCode === Key.Right) {
    socket.send(`stop-rotate|right`);
  }

  if (event.keyCode === Key.W || event.keyCode === Key.Up) {
    socket.send(`stop-thrust|forward`);
  }

  if (event.keyCode === Key.S || event.keyCode === Key.Down) {
    socket.send(`stop-thrust|backward`);
  }
});

const loop = () => {
  requestAnimationFrame(loop);
  if (entityService.localPlayer) {
    let player = entityService.getLocalPlayer().sprite.position;
    stage.position.x = config.width / 2;
    stage.position.y = config.height / 2;
    stage.pivot.x = player.x;
    stage.pivot.y = player.y;
  }
  renderer.render(stage);
  if (entityService.localPlayer) {
    let nearbyEntities = entityService.getNearby(config.radar.range);
    radar.update(nearbyEntities);
    radar.draw();
  }
};

loop();
<commit_msg>Fill the window and resize when necessary.<commit_after>import config from '../config.json';
import {autoDetectRenderer, Container, Point} from 'pixi.js';
import {Entity} from './entity';
import {Key} from './input';
import uuid from 'uuid';
import EntityService from './EntityService';
import MapService from './MapService';
import Radar from './Radar';

let name = 'top-down-arena-shooter';
let version = '0.0.1';
document.title = `${name} v${version}`;
document.body.style.backgroundColor = '#111111';
document.body.style.padding = 0;
document.body.style.margin = 0;

let renderer = autoDetectRenderer(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.view);
renderer.view.style.borderColor = '#222222';
renderer.view.style.borderStyle = 'solid';
renderer.view.style.borderWidth = '1px';

window.addEventListener('resize', (event) => {
  console.log(`window.resize event: w:${event.target.innerWidth}, h:${event.target.innerHeight}`);
  renderer.resize(event.target.innerWidth, event.target.innerHeight);
});

let stage = new Container();
let entityService = EntityService.get();
let mapService = MapService.get();
let radar = new Radar();

const getOrCreateSessionID = () => {
  if (!sessionStorage.sessionID) {
    sessionStorage.sessionID = uuid();
  }

  return sessionStorage.sessionID;
};

const handleInitializeEvent = (eventData) => {
  // input: id,x,y,r|...
  stage.removeChildren();
  entityService.clear();
  eventData = eventData.split('|');
  eventData.forEach(entityData => {
    let properties = entityData.split(',');
    let id = properties[0];
    let type = properties[1];
    let x = parseFloat(properties[2]);
    let y = parseFloat(properties[3]);
    let r = parseFloat(properties[4]);
    let w = parseFloat(properties[5]);
    let h = parseFloat(properties[6]);
    let entity = new Entity(id, type, x, y, r, w, h);
    stage.addChild(entity.sprite);
    entityService.add(entity);
  });
};

const handleMapEvent = (eventData) => {
  // input width,height
  let dimensions = eventData.split(',');
  mapService.setDimensions(dimensions[0], dimensions[1]);
};

const handleIdentityEvent = (eventData) => {
  // input: id
  entityService.setPlayerIdentity(eventData);
};

const handleAddEvent = (eventData) => {
  // input: id,x,y,r
  let properties = eventData.split(',');
  let id = properties[0];
  let type = properties[1];
  let x = parseFloat(properties[2]);
  let y = parseFloat(properties[3]);
  let r = parseFloat(properties[4]);
  let w = parseFloat(properties[5]);
  let h = parseFloat(properties[6]);
  let entity = new Entity(id, type, x, y, r, w, h);
  stage.addChild(entity.sprite);
  entityService.add(entity);
};

const handleUpdateEvent = (eventData) => {
  // input: id,x,y,r|...
  eventData = eventData.split('|');
  eventData.forEach(entityData => {
    let properties = entityData.split(',');
    let id = properties[0];
    let entity = entityService.getById(id);
    if (entity) {
      let x = parseFloat(properties[2]);
      let y = parseFloat(properties[3]);
      let r = parseFloat(properties[4]);
      let w = parseFloat(properties[5]);
      let h = parseFloat(properties[6]);
      entity.setPosition(x, y);
      entity.setRotation(r);
      entity.setSize(w, h);
    } else {
      console.log(`can't find entity: ${id}`);
    }
  });
};

const handleRemoveEvent = (eventData) => {
  // input: id
  let entity = entityService.removeById(eventData);
  if (entity) {
    stage.removeChild(entity.sprite);
  }
};

const getEventHandler = (name) => {
  switch (name) {
    case 'initialize': return handleInitializeEvent;
    case 'map': return handleMapEvent;
    case 'identity': return handleIdentityEvent;
    case 'add': return handleAddEvent;
    case 'update': return handleUpdateEvent;
    case 'remove': return handleRemoveEvent;
  }
};

let sessionID = getOrCreateSessionID();

const socket = new WebSocket(`ws://${config.server}/${sessionID}`);

socket.addEventListener('open', (event) => {
  console.log('websocket opened:', config.server);
});

socket.addEventListener('message', (event) => {
  console.log('websocket message received:', event.data);
  let split = event.data.indexOf('|');
  if (split !== -1) {
    let command = event.data.slice(0, split);
    let parameters = event.data.slice(split + 1);
    let eventHandler = getEventHandler(command);
    eventHandler(parameters);
  }
});

socket.addEventListener('close', (event) => {
  console.log('websocket closed:', config.server);
});

let keysDown = [];

window.addEventListener('keydown', (event) => {
  // console.log('keydown:', event.keyCode);
  if (keysDown.includes(event.keyCode)) return;
  keysDown.push(event.keyCode);

  if (event.keyCode === Key.A || event.keyCode === Key.Left) {
    socket.send(`start-rotate|left`);
  }

  if (event.keyCode === Key.D || event.keyCode === Key.Right) {
    socket.send(`start-rotate|right`);
  }

  if (event.keyCode === Key.W || event.keyCode === Key.Up) {
    socket.send(`start-thrust|forward`);
  }

  if (event.keyCode === Key.S || event.keyCode === Key.Down) {
    socket.send(`start-thrust|backward`);
  }
});

window.addEventListener('keyup', (event) => {
  // console.log('keyup:', event.keyCode);
  let index = keysDown.indexOf(event.keyCode);
  if (index !== -1) {
    keysDown.splice(index, 1);
  }

  if (event.keyCode === Key.A || event.keyCode === Key.Left) {
    socket.send(`stop-rotate|left`);
  }

  if (event.keyCode === Key.D || event.keyCode === Key.Right) {
    socket.send(`stop-rotate|right`);
  }

  if (event.keyCode === Key.W || event.keyCode === Key.Up) {
    socket.send(`stop-thrust|forward`);
  }

  if (event.keyCode === Key.S || event.keyCode === Key.Down) {
    socket.send(`stop-thrust|backward`);
  }
});

const loop = () => {
  requestAnimationFrame(loop);
  if (entityService.localPlayer) {
    let player = entityService.getLocalPlayer().sprite.position;
    stage.position.x = config.width / 2;
    stage.position.y = config.height / 2;
    stage.pivot.x = player.x;
    stage.pivot.y = player.y;
  }
  renderer.render(stage);
  if (entityService.localPlayer) {
    let nearbyEntities = entityService.getNearby(config.radar.range);
    radar.update(nearbyEntities);
    radar.draw();
  }
};

loop();
<|endoftext|>


<commit_before><commit_msg>add custom row<commit_after><|endoftext|>