<commit_before>import AppContext from '../../AppContext';
import ActionButton from '../common/ActionButton';
import BackButton from '../common/BackButton';
import PlansSection from '../common/PlansSection';
import {getDateString} from '../../utils/date-time';
import {getMemberActivePlan, getMemberSubscription, getPlanFromSubscription, getSitePlans, getSubscriptionFromId, isPaidMember} from '../../utils/helpers';

export const AccountPlanPageStyles = `
    .gh-portal-accountplans-main {
        margin-top: 24px;
        margin-bottom: 0;
    }

    .gh-portal-expire-container {
        margin: 24px 0 0;
    }
`;

const React = require('react');

function getConfirmationPageTitle({confirmationType}) {
    if (confirmationType === 'changePlan') {
        return 'Confirm subscription';
    } else if (confirmationType === 'cancel') {
        return 'Confirm cancellation';
    } else if (confirmationType === 'subscribe') {
        return 'Subscribe';
    }
}

const Header = ({member, lastPage, brandColor, onBack, showConfirmation, confirmationType}) => {
    let title = member.paid ? 'Change plan' : 'Choose a plan';
    if (showConfirmation) {
        title = getConfirmationPageTitle({confirmationType});
    }
    return (

            {lastPage ? <BackButton brandColor={brandColor} onClick={e => onBack(e)} /> : null}

{title}

    );
};

const CancelContinueSubscription = ({member, onCancelContinueSubscription, action, brandColor, showOnlyContinue = false}) => {
    if (!member.paid) {
        return null;
    }
    const subscription = getMemberSubscription({member});
    if (!subscription) {
        return null;
    }

    // To show only continue button and not cancellation
    if (showOnlyContinue && !subscription.cancel_at_period_end) {
        return null;
    }

    // Hide the button if subscription is due cancellation
    if (subscription.cancel_at_period_end) {
        return null;
    }
    const label = subscription.cancel_at_period_end ? 'Continue subscription' : 'Cancel subscription';
    const isRunning = ['cancelSubscription:running'].includes(action);
    const disabled = (isRunning) ? true : false;
    const isPrimary = !!subscription.cancel_at_period_end;
    const isDestructive = !subscription.cancelAtPeriodEnd;

    const CancelNotice = () => {
        if (!subscription.cancel_at_period_end) {
            return null;
        }
        const currentPeriodEnd = subscription.current_period_end;
        return (

                Your subscription will expire on {getDateString(currentPeriodEnd)}.

        );
    };

    return (

            <CancelNotice />
            <ActionButton
                onClick={(e) => {
                    onCancelContinueSubscription({
                        subscriptionId: subscription.id,
                        cancelAtPeriodEnd: !subscription.cancel_at_period_end
                    });
                }}
                isRunning={isRunning}
                disabled={disabled}
                isPrimary={isPrimary}
                isDestructive={isDestructive}
                brandColor={brandColor}
                label={label}
                style={{
                    width: '100%'
                }}
            />

    );
};

// For confirmation flows
const PlanConfirmationSection = ({action, member, plan, type, brandColor, onConfirm}) => {
    const subscription = getMemberSubscription({member});
    const isRunning = ['updateSubscription:running', 'checkoutPlan:running', 'cancelSubscription:running'].includes(action);
    const label = 'Confirm';
    let planStartDate = getDateString(subscription.current_period_end);
    const currentActivePlan = getMemberActivePlan({member});
    if (currentActivePlan.type !== plan.type) {
        planStartDate = 'immediately';
    }
    const planStartMessage = `${plan.currency}${plan.price}/${plan.type} – Starting ${planStartDate}`;
    if (type === 'changePlan') {
        return (

Account

{member.email}

Price

{planStartMessage}

                <ActionButton
                    onClick={e => onConfirm(e, plan)}
                    isRunning={isRunning}
                    isPrimary={true}
                    brandColor={brandColor}
                    label={label}
                    style={{
                        width: '100%',
                        height: '40px'
                    }}
                />

        );
    } else {
        return (

If you confirm and end your subscription now, you can still access it until {getDateString(subscription.current_period_end)}.

                <ActionButton
                    onClick={e => onConfirm(e, plan)}
                    isRunning={isRunning}
                    isPrimary={true}
                    brandColor={brandColor}
                    label={label}
                    style={{
                        width: '100%',
                        height: '40px'
                    }}
                />

        );
    }
};

// For paid members
const ChangePlanSection = ({plans, selectedPlan, member, action, brandColor, onPlanSelect, onCancelContinueSubscription}) => {
    return (

                <PlansSection
                    showLabel={false}
                    plans={plans}
                    selectedPlan={selectedPlan}
                    onPlanSelect={(e, name) => onPlanSelect(e, name)}
                />

            <CancelContinueSubscription {...{member, onCancelContinueSubscription, action, brandColor}} />

    );
};

// For free members
const UpgradePlanSection = ({
    plans, selectedPlan, action, brandColor, onPlanSelect, onPlanCheckout
}) => {
    const isRunning = ['checkoutPlan:running'].includes(action);
    let singlePlanClass = '';
    if (plans.length === 1) {
        singlePlanClass = 'singleplan';
    }
    return (

            <div className={`gh-portal-section gh-portal-accountplans-main ${singlePlanClass}`}>
                <PlansSection
                    showLabel={false}
                    plans={plans}
                    selectedPlan={selectedPlan}
                    onPlanSelect={(e, name) => onPlanSelect(e, name)}
                />

            <ActionButton
                onClick={e => onPlanCheckout(e)}
                isRunning={isRunning}
                isPrimary={true}
                brandColor={brandColor}
                label={'Continue'}
                style={{height: '40px', width: '100%', marginTop: '24px'}}
            />

    );
};

const PlansContainer = ({
    plans, selectedPlan, confirmationPlan, confirmationType,
    member, onAction, action, brandColor,showConfirmation = false,
    onPlanSelect, onPlanCheckout, onConfirm, onCancelContinueSubscription
}) => {
    // Plan upgrade flow for free member
    if (!isPaidMember({member})) {
        return (
            <UpgradePlanSection
                {...{plans, selectedPlan, member, onAction, action, brandColor, onPlanSelect, onPlanCheckout}}
            />
        );
    }

    // Plan change flow for a paid member
    if (!showConfirmation) {
        return (
            <ChangePlanSection
                {...{plans, selectedPlan, member, action, brandColor,
                    onCancelContinueSubscription, onPlanSelect}}
            />
        );
    }

    // Plan confirmation flow for cancel/update flows
    return (
        <PlanConfirmationSection
            {...{action, member, plan: confirmationPlan, type: confirmationType, onConfirm, brandColor}}
        />
    );
};
export default class AccountPlanPage extends React.Component {
    static contextType = AppContext;

    constructor(props, context) {
        super(props, context);
        this.state = this.getInitialState();
    }

    getInitialState() {
        const {member, site} = this.context;
        this.plans = getSitePlans({site, includeFree: false});
        let activePlan = getMemberActivePlan({member});
        let selectedPlan = activePlan ? this.plans.find((d) => {
            return (d.name === activePlan.name && d.price === activePlan.price && d.currency === activePlan.currency);
        }) : null;
        // Select first plan as default for free member
        if (!isPaidMember({member}) && this.plans.length > 0) {
            selectedPlan = this.plans[0];
        }
        const selectedPlanName = selectedPlan ? selectedPlan.name : null;
        return {
            selectedPlan: selectedPlanName
        };
    }

    handleSignout(e) {
        e.preventDefault();
        this.context.onAction('signout');
    }

    onBack(e) {
        if (this.state.showConfirmation) {
            this.cancelConfirmPage();
        } else {
            this.context.onAction('back');
        }
    }

    cancelConfirmPage() {
        this.setState({
            showConfirmation: false,
            confirmationPlan: null,
            confirmationType: null
        });
    }

    onPlanCheckout(e, name) {
        const {onAction, member} = this.context;
        const {confirmationPlan, selectedPlan} = this.state;
        if (member.paid) {
            const {subscriptions} = member;
            const subscriptionId = subscriptions[0].id;
            onAction('updateSubscription', {plan: confirmationPlan.name, subscriptionId, cancelAtPeriodEnd: false});
        } else {
            onAction('checkoutPlan', {plan: selectedPlan.name});
        }
    }

    onPlanSelect(e, name) {
        e.preventDefault();

        const {member} = this.context;

        // Work as checkboxes for free member plan selection and button for paid members
        if (!isPaidMember({member})) {
            // Hack: React checkbox gets out of sync with dom state with instant update
            setTimeout(() => {
                this.setState((state) => {
                    return {
                        selectedPlan: name
                    };
                });
            }, 5);
        } else {
            const confirmationPlan = this.plans.find(d => d.name === name);
            const activePlan = this.getActivePlanName({member});
            const confirmationType = activePlan ? 'changePlan' : 'subscribe';
            if (name !== this.state.selectedPlan) {
                this.setState({
                    confirmationPlan,
                    confirmationType,
                    showConfirmation: true
                });
            }
        }
    }

    onCancelContinueSubscription({subscriptionId, cancelAtPeriodEnd}) {
        const {member} = this.context;
        const subscription = getSubscriptionFromId({subscriptionId, member});
        const subscriptionPlan = getPlanFromSubscription({subscription});
        if (!cancelAtPeriodEnd) {
            this.context.onAction('cancelSubscription', {
                subscriptionId,
                cancelAtPeriodEnd
            });
        } else {
            this.setState({
                showConfirmation: true,
                confirmationPlan: subscriptionPlan,
                confirmationType: 'cancel'
            });
        }
    }

    onCancelSubscriptionConfirmation() {
        const {member} = this.context;
        const subscription = getMemberSubscription({member});
        if (!subscription) {
            return null;
        }
        this.context.onAction('cancelSubscription', {
            subscriptionId: subscription.id,
            cancelAtPeriodEnd: true
        });
    }

    getActivePlanName({member}) {
        if (member && member.paid && member.subscriptions[0]) {
            const {plan} = member.subscriptions[0];
            return plan.nickname;
        }
        return null;
    }

    onConfirm() {
        const {confirmationType} = this.state;
        if (confirmationType === 'cancel') {
            return this.onCancelSubscriptionConfirmation();
        } else if (['changePlan', 'subscribe'].includes(confirmationType)) {
            return this.onPlanCheckout();
        }
    }

    render() {
        const {member, brandColor, lastPage} = this.context;
        const plans = this.plans;
        const {selectedPlan, showConfirmation, confirmationPlan, confirmationType} = this.state;
        return (

                     this.onBack(e)}
                        confirmationType = {confirmationType}
                        showConfirmation = {showConfirmation}
                    />
                    <PlansContainer
                        {...this.context}
                        {...{plans, selectedPlan, showConfirmation, confirmationPlan, confirmationType}}
                        onConfirm = {() => this.onConfirm()}
                        onCancelContinueSubscription = {data => this.onCancelContinueSubscription(data)}
                        onPlanSelect = {(e, name) => this.onPlanSelect(e, name)}
                        onPlanCheckout = {(e, name) => this.onPlanCheckout(e, name)}
                    />

        );
    }
}<commit_msg>Fixed stripe checkout not working on plan upgarde<commit_after>import AppContext from '../../AppContext';
import ActionButton from '../common/ActionButton';
import BackButton from '../common/BackButton';
import PlansSection from '../common/PlansSection';
import {getDateString} from '../../utils/date-time';
import {getMemberActivePlan, getMemberSubscription, getPlanFromSubscription, getSitePlans, getSubscriptionFromId, isPaidMember} from '../../utils/helpers';

export const AccountPlanPageStyles = `
    .gh-portal-accountplans-main {
        margin-top: 24px;
        margin-bottom: 0;
    }

    .gh-portal-expire-container {
        margin: 24px 0 0;
    }
`;

const React = require('react');

function getConfirmationPageTitle({confirmationType}) {
    if (confirmationType === 'changePlan') {
        return 'Confirm subscription';
    } else if (confirmationType === 'cancel') {
        return 'Confirm cancellation';
    } else if (confirmationType === 'subscribe') {
        return 'Subscribe';
    }
}

const Header = ({member, lastPage, brandColor, onBack, showConfirmation, confirmationType}) => {
    let title = member.paid ? 'Change plan' : 'Choose a plan';
    if (showConfirmation) {
        title = getConfirmationPageTitle({confirmationType});
    }
    return (

            {lastPage ? <BackButton brandColor={brandColor} onClick={e => onBack(e)} /> : null}

{title}

    );
};

const CancelContinueSubscription = ({member, onCancelContinueSubscription, action, brandColor, showOnlyContinue = false}) => {
    if (!member.paid) {
        return null;
    }
    const subscription = getMemberSubscription({member});
    if (!subscription) {
        return null;
    }

    // To show only continue button and not cancellation
    if (showOnlyContinue && !subscription.cancel_at_period_end) {
        return null;
    }

    // Hide the button if subscription is due cancellation
    if (subscription.cancel_at_period_end) {
        return null;
    }
    const label = subscription.cancel_at_period_end ? 'Continue subscription' : 'Cancel subscription';
    const isRunning = ['cancelSubscription:running'].includes(action);
    const disabled = (isRunning) ? true : false;
    const isPrimary = !!subscription.cancel_at_period_end;
    const isDestructive = !subscription.cancelAtPeriodEnd;

    const CancelNotice = () => {
        if (!subscription.cancel_at_period_end) {
            return null;
        }
        const currentPeriodEnd = subscription.current_period_end;
        return (

                Your subscription will expire on {getDateString(currentPeriodEnd)}.

        );
    };

    return (

            <CancelNotice />
            <ActionButton
                onClick={(e) => {
                    onCancelContinueSubscription({
                        subscriptionId: subscription.id,
                        cancelAtPeriodEnd: !subscription.cancel_at_period_end
                    });
                }}
                isRunning={isRunning}
                disabled={disabled}
                isPrimary={isPrimary}
                isDestructive={isDestructive}
                brandColor={brandColor}
                label={label}
                style={{
                    width: '100%'
                }}
            />

    );
};

// For confirmation flows
const PlanConfirmationSection = ({action, member, plan, type, brandColor, onConfirm}) => {
    const subscription = getMemberSubscription({member});
    const isRunning = ['updateSubscription:running', 'checkoutPlan:running', 'cancelSubscription:running'].includes(action);
    const label = 'Confirm';
    let planStartDate = getDateString(subscription.current_period_end);
    const currentActivePlan = getMemberActivePlan({member});
    if (currentActivePlan.type !== plan.type) {
        planStartDate = 'immediately';
    }
    const planStartMessage = `${plan.currency}${plan.price}/${plan.type} – Starting ${planStartDate}`;
    if (type === 'changePlan') {
        return (

Account

{member.email}

Price

{planStartMessage}

                <ActionButton
                    onClick={e => onConfirm(e, plan)}
                    isRunning={isRunning}
                    isPrimary={true}
                    brandColor={brandColor}
                    label={label}
                    style={{
                        width: '100%',
                        height: '40px'
                    }}
                />

        );
    } else {
        return (

If you confirm and end your subscription now, you can still access it until {getDateString(subscription.current_period_end)}.

                <ActionButton
                    onClick={e => onConfirm(e, plan)}
                    isRunning={isRunning}
                    isPrimary={true}
                    brandColor={brandColor}
                    label={label}
                    style={{
                        width: '100%',
                        height: '40px'
                    }}
                />

        );
    }
};

// For paid members
const ChangePlanSection = ({plans, selectedPlan, member, action, brandColor, onPlanSelect, onCancelContinueSubscription}) => {
    return (

                <PlansSection
                    showLabel={false}
                    plans={plans}
                    selectedPlan={selectedPlan}
                    onPlanSelect={(e, name) => onPlanSelect(e, name)}
                />

            <CancelContinueSubscription {...{member, onCancelContinueSubscription, action, brandColor}} />

    );
};

// For free members
const UpgradePlanSection = ({
    plans, selectedPlan, action, brandColor, onPlanSelect, onPlanCheckout
}) => {
    const isRunning = ['checkoutPlan:running'].includes(action);
    let singlePlanClass = '';
    if (plans.length === 1) {
        singlePlanClass = 'singleplan';
    }
    return (

            <div className={`gh-portal-section gh-portal-accountplans-main ${singlePlanClass}`}>
                <PlansSection
                    showLabel={false}
                    plans={plans}
                    selectedPlan={selectedPlan}
                    onPlanSelect={(e, name) => onPlanSelect(e, name)}
                />

            <ActionButton
                onClick={e => onPlanCheckout(e)}
                isRunning={isRunning}
                isPrimary={true}
                brandColor={brandColor}
                label={'Continue'}
                style={{height: '40px', width: '100%', marginTop: '24px'}}
            />

    );
};

const PlansContainer = ({
    plans, selectedPlan, confirmationPlan, confirmationType,
    member, onAction, action, brandColor,showConfirmation = false,
    onPlanSelect, onPlanCheckout, onConfirm, onCancelContinueSubscription
}) => {
    // Plan upgrade flow for free member
    if (!isPaidMember({member})) {
        return (
            <UpgradePlanSection
                {...{plans, selectedPlan, member, onAction, action, brandColor, onPlanSelect, onPlanCheckout}}
            />
        );
    }

    // Plan change flow for a paid member
    if (!showConfirmation) {
        return (
            <ChangePlanSection
                {...{plans, selectedPlan, member, action, brandColor,
                    onCancelContinueSubscription, onPlanSelect}}
            />
        );
    }

    // Plan confirmation flow for cancel/update flows
    return (
        <PlanConfirmationSection
            {...{action, member, plan: confirmationPlan, type: confirmationType, onConfirm, brandColor}}
        />
    );
};
export default class AccountPlanPage extends React.Component {
    static contextType = AppContext;

    constructor(props, context) {
        super(props, context);
        this.state = this.getInitialState();
    }

    getInitialState() {
        const {member, site} = this.context;
        this.plans = getSitePlans({site, includeFree: false});
        let activePlan = getMemberActivePlan({member});
        let selectedPlan = activePlan ? this.plans.find((d) => {
            return (d.name === activePlan.name && d.price === activePlan.price && d.currency === activePlan.currency);
        }) : null;
        // Select first plan as default for free member
        if (!isPaidMember({member}) && this.plans.length > 0) {
            selectedPlan = this.plans[0];
        }
        const selectedPlanName = selectedPlan ? selectedPlan.name : null;
        return {
            selectedPlan: selectedPlanName
        };
    }

    handleSignout(e) {
        e.preventDefault();
        this.context.onAction('signout');
    }

    onBack(e) {
        if (this.state.showConfirmation) {
            this.cancelConfirmPage();
        } else {
            this.context.onAction('back');
        }
    }

    cancelConfirmPage() {
        this.setState({
            showConfirmation: false,
            confirmationPlan: null,
            confirmationType: null
        });
    }

    onPlanCheckout(e, name) {
        const {onAction, member} = this.context;
        const {confirmationPlan, selectedPlan} = this.state;
        if (member.paid) {
            const {subscriptions} = member;
            const subscriptionId = subscriptions[0].id;
            onAction('updateSubscription', {plan: confirmationPlan.name, subscriptionId, cancelAtPeriodEnd: false});
        } else {
            onAction('checkoutPlan', {plan: selectedPlan});
        }
    }

    onPlanSelect(e, name) {
        e.preventDefault();

        const {member} = this.context;

        // Work as checkboxes for free member plan selection and button for paid members
        if (!isPaidMember({member})) {
            // Hack: React checkbox gets out of sync with dom state with instant update
            setTimeout(() => {
                this.setState((state) => {
                    return {
                        selectedPlan: name
                    };
                });
            }, 5);
        } else {
            const confirmationPlan = this.plans.find(d => d.name === name);
            const activePlan = this.getActivePlanName({member});
            const confirmationType = activePlan ? 'changePlan' : 'subscribe';
            if (name !== this.state.selectedPlan) {
                this.setState({
                    confirmationPlan,
                    confirmationType,
                    showConfirmation: true
                });
            }
        }
    }

    onCancelContinueSubscription({subscriptionId, cancelAtPeriodEnd}) {
        const {member} = this.context;
        const subscription = getSubscriptionFromId({subscriptionId, member});
        const subscriptionPlan = getPlanFromSubscription({subscription});
        if (!cancelAtPeriodEnd) {
            this.context.onAction('cancelSubscription', {
                subscriptionId,
                cancelAtPeriodEnd
            });
        } else {
            this.setState({
                showConfirmation: true,
                confirmationPlan: subscriptionPlan,
                confirmationType: 'cancel'
            });
        }
    }

    onCancelSubscriptionConfirmation() {
        const {member} = this.context;
        const subscription = getMemberSubscription({member});
        if (!subscription) {
            return null;
        }
        this.context.onAction('cancelSubscription', {
            subscriptionId: subscription.id,
            cancelAtPeriodEnd: true
        });
    }

    getActivePlanName({member}) {
        if (member && member.paid && member.subscriptions[0]) {
            const {plan} = member.subscriptions[0];
            return plan.nickname;
        }
        return null;
    }

    onConfirm() {
        const {confirmationType} = this.state;
        if (confirmationType === 'cancel') {
            return this.onCancelSubscriptionConfirmation();
        } else if (['changePlan', 'subscribe'].includes(confirmationType)) {
            return this.onPlanCheckout();
        }
    }

    render() {
        const {member, brandColor, lastPage} = this.context;
        const plans = this.plans;
        const {selectedPlan, showConfirmation, confirmationPlan, confirmationType} = this.state;
        return (

                     this.onBack(e)}
                        confirmationType = {confirmationType}
                        showConfirmation = {showConfirmation}
                    />
                    <PlansContainer
                        {...this.context}
                        {...{plans, selectedPlan, showConfirmation, confirmationPlan, confirmationType}}
                        onConfirm = {() => this.onConfirm()}
                        onCancelContinueSubscription = {data => this.onCancelContinueSubscription(data)}
                        onPlanSelect = {(e, name) => this.onPlanSelect(e, name)}
                        onPlanCheckout = {(e, name) => this.onPlanCheckout(e, name)}
                    />

        );
    }
}<|endoftext|>


<commit_before>var Tournament = require('./Tournament');
var Entity = require('../entity');

function HungerGames() {
    Tournament.apply(this, Array.prototype.slice.call(arguments));

    this.ID = 11;
    this.name = "Hunger Games";

    // Gamemode Specific Variables
    this.maxContenders = 12;
    this.baseSpawnPoints = [{
            x: 1600,
            y: 200
        }, {
            x: 3200,
            y: 200
        }, {
            x: 4800,
            y: 200
        }, // Top
        {
            x: 200,
            y: 1600
        }, {
            x: 200,
            y: 3200
        }, {
            x: 200,
            y: 4800
        }, // Left
        {
            x: 6200,
            y: 1600
        }, {
            x: 6200,
            y: 3200
        }, {
            x: 6200,
            y: 4800
        }, // Right
        {
            x: 1600,
            y: 6200
        }, {
            x: 3200,
            y: 6200
        }, {
            x: 4800,
            y: 6200
        } // Bottom
    ];
    this.contenderSpawnPoints;
    this.borderDec = 100; // Border shrinks by this size everytime someone dies
}

module.exports = HungerGames;
HungerGames.prototype = new Tournament();

// Gamemode Specific Functions

HungerGames.prototype.getPos = function () {
    var pos = {
        x: 0,
        y: 0
    };

    // Random Position
    if (this.contenderSpawnPoints.length > 0) {
        var index = Math.floor(Math.random() * this.contenderSpawnPoints.length);
        pos = this.contenderSpawnPoints[index];
        this.contenderSpawnPoints.splice(index, 1);
    }

    return {
        x: pos.x,
        y: pos.y
    };
};

HungerGames.prototype.spawnFood = function (gameServer, mass, pos) {
    var cell = new Entity.Food(gameServer, null, pos, mass);
    cell.setColor(gameServer.getRandomColor());
    gameServer.addNode(cell);
};

HungerGames.prototype.spawnVirus = function (gameServer, pos) {
    var v = new Entity.Virus(gameServer, null, pos, gameServer.config.virusMinSize);
    gameServer.addNode(v);
};

HungerGames.prototype.onPlayerDeath = function (gameServer) {
    gameServer.setBorder(
        gameServer.border.width - this.borderDec * 2,
        gameServer.border.height - this.borderDec * 2);

    // Remove all cells
    var len = gameServer.nodes.length;
    for (var i = 0; i < len; i++) {
        var node = gameServer.nodes[i];

        if ((!node) || (node.getType() == 0)) {
            continue;
        }

        // Move
        if (node.position.x < gameServer.border.minx) {
            gameServer.removeNode(node);
            i--;
        } else if (node.position.x > gameServer.border.maxx) {
            gameServer.removeNode(node);
            i--;
        } else if (node.position.y < gameServer.border.miny) {
            gameServer.removeNode(node);
            i--;
        } else if (node.position.y > gameServer.border.maxy) {
            gameServer.removeNode(node);
            i--;
        }
    }
};

// Override

HungerGames.prototype.onServerInit = function (gameServer) {
    // Prepare
    this.prepare(gameServer);

    // Resets spawn points
    this.contenderSpawnPoints = this.baseSpawnPoints.slice();

    // Override config values
    if (gameServer.config.serverBots > this.maxContenders) {
        // The number of bots cannot exceed the maximum amount of contenders
        gameServer.config.serverBots = this.maxContenders;
    }
    gameServer.config.spawnInterval = 20;
    gameServer.config.borderWidth = 3200;
    gameServer.config.borderHeight = 3200;
    gameServer.config.foodSpawnAmount = 5; // This is hunger games
    gameServer.config.foodMinAmount = 100;
    gameServer.config.foodMaxAmount = 200;
    gameServer.config.foodMinSize = 10; // Food is scarce, but its worth more
    gameServer.config.virusMinAmount = 10; // We need to spawn some viruses in case someone eats them all
    gameServer.config.virusMaxAmount = 100;
    gameServer.config.ejectSpawnPlayer = 0;
    gameServer.config.playerDisconnectTime = 10; // So that people dont disconnect and stall the game for too long

    // Spawn Initial Virus/Large food
    var mapWidth = gameServer.border.width;
    var mapHeight = gameServer.border.height;

    // Food
    this.spawnFood(gameServer, 200, {
        x: mapWidth * .5,
        y: mapHeight * .5
    }); // Center
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .4,
        y: mapHeight * .6
    }); //
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .6,
        y: mapHeight * .6
    });
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .4,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .6,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .7,
        y: mapHeight * .5
    }); //
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .3,
        y: mapHeight * .5
    });
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .5,
        y: mapHeight * .7
    });
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .5,
        y: mapHeight * .3
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .7,
        y: mapHeight * .625
    }); // Corner
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .625,
        y: mapHeight * .7
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .3,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .4,
        y: mapHeight * .3
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .6,
        y: mapHeight * .3
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .7,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .3,
        y: mapHeight * .6
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .4,
        y: mapHeight * .7
    });

    // Virus
    this.spawnVirus(gameServer, {
        x: mapWidth * .6,
        y: mapHeight * .5
    }); //
    this.spawnVirus(gameServer, {
        x: mapWidth * .4,
        y: mapHeight * .5
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .5,
        y: mapHeight * .4
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .5,
        y: mapHeight * .6
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .3,
        y: mapHeight * .3
    }); //
    this.spawnVirus(gameServer, {
        x: mapWidth * .3,
        y: mapHeight * .7
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .7,
        y: mapHeight * .3
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .7,
        y: mapHeight * .7
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .25,
        y: mapHeight * .6
    }); //
    this.spawnVirus(gameServer, {
        x: mapWidth * .25,
        y: mapHeight * .4
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .75,
        y: mapHeight * .6
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .75,
        y: mapHeight * .4
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .6,
        y: mapHeight * .25
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .4,
        y: mapHeight * .25
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .6,
        y: mapHeight * .75
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .4,
        y: mapHeight * .75
    });
};

HungerGames.prototype.onPlayerSpawn = function (gameServer, player) {
    // Only spawn players if the game hasnt started yet
    if ((this.gamePhase == 0) && (this.contenders.length < this.maxContenders)) {
        player.setColor(gameServer.getRandomColor()); // Random color
        this.contenders.push(player); // Add to contenders list
        gameServer.spawnPlayer(player, this.getPos());

        if (this.contenders.length == this.maxContenders) {
            // Start the game once there is enough players
            this.startGamePrep(gameServer);
        }
    }
};
<commit_msg>Update HungerGames.js<commit_after>var Tournament = require('./Tournament');
var Entity = require('../entity');

function HungerGames() {
    Tournament.apply(this, Array.prototype.slice.call(arguments));

    this.ID = 11;
    this.name = "Hunger Games";

    // Gamemode Specific Variables
    this.maxContenders = 12;
    this.baseSpawnPoints = [{
            x: 1600,
            y: 200
        }, {
            x: 3200,
            y: 200
        }, {
            x: 4800,
            y: 200
        }, // Top
        {
            x: 200,
            y: 1600
        }, {
            x: 200,
            y: 3200
        }, {
            x: 200,
            y: 4800
        }, // Left
        {
            x: 6200,
            y: 1600
        }, {
            x: 6200,
            y: 3200
        }, {
            x: 6200,
            y: 4800
        }, // Right
        {
            x: 1600,
            y: 6200
        }, {
            x: 3200,
            y: 6200
        }, {
            x: 4800,
            y: 6200
        } // Bottom
    ];
    this.contenderSpawnPoints;
    this.borderDec = 100; // Border shrinks by this size everytime someone dies
}

module.exports = HungerGames;
HungerGames.prototype = new Tournament();

// Gamemode Specific Functions

HungerGames.prototype.getPos = function () {
    var pos = {
        x: 0,
        y: 0
    };

    // Random Position
    if (this.contenderSpawnPoints.length > 0) {
        var index = Math.floor(Math.random() * this.contenderSpawnPoints.length);
        pos = this.contenderSpawnPoints[index];
        this.contenderSpawnPoints.splice(index, 1);
    }

    return {
        x: pos.x,
        y: pos.y
    };
};

HungerGames.prototype.spawnFood = function (gameServer, mass, pos) {
    var cell = new Entity.Food(gameServer, null, pos, mass);
    cell.setColor(gameServer.getRandomColor());
    gameServer.addNode(cell);
};

HungerGames.prototype.spawnVirus = function (gameServer, pos) {
    var v = new Entity.Virus(gameServer, null, pos, gameServer.config.virusMinSize);
    gameServer.addNode(v);
};

HungerGames.prototype.onPlayerDeath = function (gameServer) {
    gameServer.setBorder(
        gameServer.border.width - this.borderDec * 2,
        gameServer.border.height - this.borderDec * 2);

    // Remove all cells
    var len = gameServer.nodes.length;
    for (var i = 0; i < len; i++) {
        var node = gameServer.nodes[i];

        if ((!node) || (node.cellType == 0)) {
            continue;
        }

        // Move
        if (node.position.x < gameServer.border.minx) {
            gameServer.removeNode(node);
            i--;
        } else if (node.position.x > gameServer.border.maxx) {
            gameServer.removeNode(node);
            i--;
        } else if (node.position.y < gameServer.border.miny) {
            gameServer.removeNode(node);
            i--;
        } else if (node.position.y > gameServer.border.maxy) {
            gameServer.removeNode(node);
            i--;
        }
    }
};

// Override

HungerGames.prototype.onServerInit = function (gameServer) {
    // Prepare
    this.prepare(gameServer);

    // Resets spawn points
    this.contenderSpawnPoints = this.baseSpawnPoints.slice();

    // Override config values
    if (gameServer.config.serverBots > this.maxContenders) {
        // The number of bots cannot exceed the maximum amount of contenders
        gameServer.config.serverBots = this.maxContenders;
    }
    gameServer.config.spawnInterval = 20;
    gameServer.config.borderWidth = 3200;
    gameServer.config.borderHeight = 3200;
    gameServer.config.foodSpawnAmount = 5; // This is hunger games
    gameServer.config.foodMinAmount = 100;
    gameServer.config.foodMaxAmount = 200;
    gameServer.config.foodMinSize = 10; // Food is scarce, but its worth more
    gameServer.config.virusMinAmount = 10; // We need to spawn some viruses in case someone eats them all
    gameServer.config.virusMaxAmount = 100;
    gameServer.config.ejectSpawnPlayer = 0;
    gameServer.config.playerDisconnectTime = 10; // So that people dont disconnect and stall the game for too long

    // Spawn Initial Virus/Large food
    var mapWidth = gameServer.border.width;
    var mapHeight = gameServer.border.height;

    // Food
    this.spawnFood(gameServer, 200, {
        x: mapWidth * .5,
        y: mapHeight * .5
    }); // Center
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .4,
        y: mapHeight * .6
    }); //
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .6,
        y: mapHeight * .6
    });
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .4,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 80, {
        x: mapWidth * .6,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .7,
        y: mapHeight * .5
    }); //
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .3,
        y: mapHeight * .5
    });
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .5,
        y: mapHeight * .7
    });
    this.spawnFood(gameServer, 50, {
        x: mapWidth * .5,
        y: mapHeight * .3
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .7,
        y: mapHeight * .625
    }); // Corner
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .625,
        y: mapHeight * .7
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .3,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .4,
        y: mapHeight * .3
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .6,
        y: mapHeight * .3
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .7,
        y: mapHeight * .4
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .3,
        y: mapHeight * .6
    });
    this.spawnFood(gameServer, 30, {
        x: mapWidth * .4,
        y: mapHeight * .7
    });

    // Virus
    this.spawnVirus(gameServer, {
        x: mapWidth * .6,
        y: mapHeight * .5
    }); //
    this.spawnVirus(gameServer, {
        x: mapWidth * .4,
        y: mapHeight * .5
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .5,
        y: mapHeight * .4
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .5,
        y: mapHeight * .6
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .3,
        y: mapHeight * .3
    }); //
    this.spawnVirus(gameServer, {
        x: mapWidth * .3,
        y: mapHeight * .7
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .7,
        y: mapHeight * .3
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .7,
        y: mapHeight * .7
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .25,
        y: mapHeight * .6
    }); //
    this.spawnVirus(gameServer, {
        x: mapWidth * .25,
        y: mapHeight * .4
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .75,
        y: mapHeight * .6
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .75,
        y: mapHeight * .4
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .6,
        y: mapHeight * .25
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .4,
        y: mapHeight * .25
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .6,
        y: mapHeight * .75
    });
    this.spawnVirus(gameServer, {
        x: mapWidth * .4,
        y: mapHeight * .75
    });
};

HungerGames.prototype.onPlayerSpawn = function (gameServer, player) {
    // Only spawn players if the game hasnt started yet
    if ((this.gamePhase == 0) && (this.contenders.length < this.maxContenders)) {
        player.setColor(gameServer.getRandomColor()); // Random color
        this.contenders.push(player); // Add to contenders list
        gameServer.spawnPlayer(player, this.getPos());

        if (this.contenders.length == this.maxContenders) {
            // Start the game once there is enough players
            this.startGamePrep(gameServer);
        }
    }
};
<|endoftext|>


<commit_before>import { moduleForComponent, test } from 'ember-qunit';
import Ember from 'ember';
import { TextMode, TextHighlightRules, Range } from 'ember-ace';
import PageObject from 'ember-cli-page-object';
import aceComponent from 'dummy/tests/components/ember-ace';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';

moduleForComponent('ember-ace', 'Integration | Component | ember ace', {
  integration: true,

  beforeEach() {
    this.component = PageObject.create(aceComponent);
    this.component.setContext(this);
  },

  afterEach() {
    this.component.removeContext();
  }
});

test('rendering a given value', function(assert) {
  this.set('value', 'function() {\n  console.log("hi");\n}');
  this.render(hbs`{{ember-ace lines=3 value=value}}`);

  assert.equal(this.component.lines().count, 3);
  assert.equal(this.component.value, this.get('value'));

  Ember.run(() => this.set('value', '// nevermind'));
  assert.equal(this.component.lines().count, 1);
  assert.equal(this.component.value, this.get('value'));
});

test('leading, trailing and internal whitespace', function(assert) {
  this.set('value', '\n\na\n  \nb\n\n');
  this.render(hbs`{{ember-ace lines=10 value=value}}`);

  assert.equal(this.component.lines().count, 7);
  assert.equal(this.component.value, this.get('value').trim());
});

test('notifying value updates', function(assert) {
  this.set('change', sinon.spy());
  this.render(hbs`{{ember-ace lines=1 update=(action change)}}`);

  this.component.setValue('hello');
  assert.ok(this.get('change').calledWith('hello'));
  assert.equal(this.component.value, 'hello');
});

test('setting a theme', function(assert) {
  this.set('theme', 'ace/theme/tomorrow_night_eighties');
  this.render(hbs`{{ember-ace theme=theme}}`);
  assert.ok(this.$('.ace_editor').is('.ace-tomorrow-night-eighties'));

  Ember.run(() => this.set('theme', 'ace/theme/chaos'));
  assert.ok(this.$('.ace_editor').is('.ace-chaos'));
});

test('annotating lines', function(assert) {
  this.set('annotations', [{ type: 'warning', row: 1 }]);
  this.set('value', 'hello\nworld');
  this.render(hbs`{{ember-ace lines=3 annotations=annotations value=value}}`);
  assert.equal(this.component.annotations().count, 1);
  assert.equal(this.component.annotations(0).type, 'warning');
  assert.equal(this.component.annotations(0).row, 1);

  Ember.run(() => this.set('annotations', [{ type: 'error', row: 0 }]));
  assert.equal(this.component.annotations().count, 1);
  assert.equal(this.component.annotations(0).type, 'error');
  assert.equal(this.component.annotations(0).row, 0);

  Ember.run(() => this.set('annotations', []));
  assert.equal(this.component.annotations().count, 0);
});

test('front range markers', function(assert) {
  this.set('value', 'hello\neveryone\nin the world');
  this.set('markers', [
    { class: 'foo', range: new Range(0, 0, 1, 1) },
    { class: 'bar', range: new Range(2, 0, 2, 5) }
  ]);
  this.render(hbs`{{ember-ace lines=3 markers=markers value=value}}`);
  assert.equal(this.component.backMarkers().count, 0);
  assert.equal(this.component.frontMarkers().count, 2);
  assert.equal(this.component.frontMarkers(0).type, 'foo');
  assert.equal(this.component.frontMarkers(0).segmentCount, 2);
  assert.equal(this.component.frontMarkers(1).type, 'bar');
  assert.equal(this.component.frontMarkers(1).segmentCount, 1);

  Ember.run(() => this.set('markers', [{ class: 'baz', range: new Range(1, 0, 1, 1) }]));
  assert.equal(this.component.frontMarkers().count, 1);
  assert.equal(this.component.frontMarkers(0).type, 'baz');
  assert.equal(this.component.frontMarkers(0).segmentCount, 1);

  Ember.run(() => this.set('markers', []));
  assert.equal(this.component.frontMarkers().count, 0);
});

test('back range markers', function(assert) {
  this.set('value', 'hello\neveryone\nin the world');
  this.set('markers', [
    { class: 'foo', range: new Range(0, 0, 1, 1), inFront: false },
    { class: 'bar', range: new Range(2, 0, 2, 5), inFront: false }
  ]);
  this.render(hbs`{{ember-ace lines=3 markers=markers value=value}}`);
  assert.equal(this.component.frontMarkers().count, 0);
  assert.equal(this.component.backMarkers().count, 2);
  assert.equal(this.component.backMarkers(0).type, 'foo');
  assert.equal(this.component.backMarkers(0).segmentCount, 2);
  assert.equal(this.component.backMarkers(1).type, 'bar');
  assert.equal(this.component.backMarkers(1).segmentCount, 1);

  Ember.run(() => this.set('markers', [{ class: 'baz', range: new Range(1, 0, 1, 1), inFront: false }]));
  assert.equal(this.component.backMarkers().count, 1);
  assert.equal(this.component.backMarkers(0).type, 'baz');
  assert.equal(this.component.backMarkers(0).segmentCount, 1);

  Ember.run(() => this.set('markers', []));
  assert.equal(this.component.backMarkers().count, 0);
});

test('setting a custom mode', function(assert) {
  const NumberMode = makeMode({
    start: [
      { regex: '[-+]?[0-9]+', token: 'constant.numeric' },
      { defaultToken: 'other' }
    ]
  });

  this.set('mode', new NumberMode());
  this.set('value', 'abc 123\n!@# 456 foo');
  this.render(hbs`{{ember-ace mode=mode value=value}}`);
  assert.deepEqual(this.component.lines(0).tokens().mapBy('type'), ['other', 'constant.numeric']);
  assert.deepEqual(this.component.lines(1).tokens().mapBy('type'), ['other', 'constant.numeric', 'other']);

  const VariableMode = makeMode({
    start: [
      { regex: '[a-zA-Z]+', token: 'variable' },
      { defaultToken: 'other' }
    ]
  });

  Ember.run(() => this.set('mode', new VariableMode()));
  assert.deepEqual(this.component.lines(0).tokens().mapBy('type'), ['variable', 'other']);
  assert.deepEqual(this.component.lines(1).tokens().mapBy('type'), ['other', 'variable']);
});

function makeMode(rules) {
  return class extends TextMode {
    constructor() {
      super();
      this.HighlightRules = class extends TextHighlightRules {
        constructor() {
          super();
          this.$rules = rules;
        }
      }
    }
  }
}
<commit_msg>Fix test<commit_after>import { moduleForComponent, test } from 'ember-qunit';
import Ember from 'ember';
import { TextMode, TextHighlightRules, Range } from 'ember-ace';
import PageObject from 'ember-cli-page-object';
import aceComponent from 'dummy/tests/components/ember-ace';
import hbs from 'htmlbars-inline-precompile';
import sinon from 'sinon';

moduleForComponent('ember-ace', 'Integration | Component | ember ace', {
  integration: true,

  beforeEach() {
    this.component = PageObject.create(aceComponent);
    this.component.setContext(this);
  },

  afterEach() {
    this.component.removeContext();
  }
});

test('rendering a given value', function(assert) {
  this.set('value', 'function() {\n  console.log("hi");\n}');
  this.render(hbs`{{ember-ace lines=3 value=value}}`);

  assert.equal(this.component.lines().count, 3);
  assert.equal(this.component.value, this.get('value'));

  Ember.run(() => this.set('value', '// nevermind'));
  assert.equal(this.component.lines().count, 1);
  assert.equal(this.component.value, this.get('value'));
});

test('leading, trailing and internal whitespace', function(assert) {
  this.set('value', '\n\na\n  \nb\n\n');
  this.render(hbs`{{ember-ace lines=10 value=value}}`);

  assert.equal(this.component.lines().count, 7);
  assert.equal(this.component.value, this.get('value').trim());
});

test('notifying value updates', function(assert) {
  this.set('change', sinon.spy());
  this.render(hbs`{{ember-ace lines=1 update=(action change)}}`);

  this.component.setValue('hello');
  assert.ok(this.get('change').calledWith('hello'));
  assert.equal(this.component.value, 'hello');
});

test('setting a theme', function(assert) {
  this.set('theme', 'ace/theme/ambiance');
  this.render(hbs`{{ember-ace theme=theme}}`);
  assert.ok(this.$('.ace_editor').is('.ace-ambiance'));

  Ember.run(() => this.set('theme', 'ace/theme/chaos'));
  assert.ok(this.$('.ace_editor').is('.ace-chaos'));
});

test('annotating lines', function(assert) {
  this.set('annotations', [{ type: 'warning', row: 1 }]);
  this.set('value', 'hello\nworld');
  this.render(hbs`{{ember-ace lines=3 annotations=annotations value=value}}`);
  assert.equal(this.component.annotations().count, 1);
  assert.equal(this.component.annotations(0).type, 'warning');
  assert.equal(this.component.annotations(0).row, 1);

  Ember.run(() => this.set('annotations', [{ type: 'error', row: 0 }]));
  assert.equal(this.component.annotations().count, 1);
  assert.equal(this.component.annotations(0).type, 'error');
  assert.equal(this.component.annotations(0).row, 0);

  Ember.run(() => this.set('annotations', []));
  assert.equal(this.component.annotations().count, 0);
});

test('front range markers', function(assert) {
  this.set('value', 'hello\neveryone\nin the world');
  this.set('markers', [
    { class: 'foo', range: new Range(0, 0, 1, 1) },
    { class: 'bar', range: new Range(2, 0, 2, 5) }
  ]);
  this.render(hbs`{{ember-ace lines=3 markers=markers value=value}}`);
  assert.equal(this.component.backMarkers().count, 0);
  assert.equal(this.component.frontMarkers().count, 2);
  assert.equal(this.component.frontMarkers(0).type, 'foo');
  assert.equal(this.component.frontMarkers(0).segmentCount, 2);
  assert.equal(this.component.frontMarkers(1).type, 'bar');
  assert.equal(this.component.frontMarkers(1).segmentCount, 1);

  Ember.run(() => this.set('markers', [{ class: 'baz', range: new Range(1, 0, 1, 1) }]));
  assert.equal(this.component.frontMarkers().count, 1);
  assert.equal(this.component.frontMarkers(0).type, 'baz');
  assert.equal(this.component.frontMarkers(0).segmentCount, 1);

  Ember.run(() => this.set('markers', []));
  assert.equal(this.component.frontMarkers().count, 0);
});

test('back range markers', function(assert) {
  this.set('value', 'hello\neveryone\nin the world');
  this.set('markers', [
    { class: 'foo', range: new Range(0, 0, 1, 1), inFront: false },
    { class: 'bar', range: new Range(2, 0, 2, 5), inFront: false }
  ]);
  this.render(hbs`{{ember-ace lines=3 markers=markers value=value}}`);
  assert.equal(this.component.frontMarkers().count, 0);
  assert.equal(this.component.backMarkers().count, 2);
  assert.equal(this.component.backMarkers(0).type, 'foo');
  assert.equal(this.component.backMarkers(0).segmentCount, 2);
  assert.equal(this.component.backMarkers(1).type, 'bar');
  assert.equal(this.component.backMarkers(1).segmentCount, 1);

  Ember.run(() => this.set('markers', [{ class: 'baz', range: new Range(1, 0, 1, 1), inFront: false }]));
  assert.equal(this.component.backMarkers().count, 1);
  assert.equal(this.component.backMarkers(0).type, 'baz');
  assert.equal(this.component.backMarkers(0).segmentCount, 1);

  Ember.run(() => this.set('markers', []));
  assert.equal(this.component.backMarkers().count, 0);
});

test('setting a custom mode', function(assert) {
  const NumberMode = makeMode({
    start: [
      { regex: '[-+]?[0-9]+', token: 'constant.numeric' },
      { defaultToken: 'other' }
    ]
  });

  this.set('mode', new NumberMode());
  this.set('value', 'abc 123\n!@# 456 foo');
  this.render(hbs`{{ember-ace mode=mode value=value}}`);
  assert.deepEqual(this.component.lines(0).tokens().mapBy('type'), ['other', 'constant.numeric']);
  assert.deepEqual(this.component.lines(1).tokens().mapBy('type'), ['other', 'constant.numeric', 'other']);

  const VariableMode = makeMode({
    start: [
      { regex: '[a-zA-Z]+', token: 'variable' },
      { defaultToken: 'other' }
    ]
  });

  Ember.run(() => this.set('mode', new VariableMode()));
  assert.deepEqual(this.component.lines(0).tokens().mapBy('type'), ['variable', 'other']);
  assert.deepEqual(this.component.lines(1).tokens().mapBy('type'), ['other', 'variable']);
});

function makeMode(rules) {
  return class extends TextMode {
    constructor() {
      super();
      this.HighlightRules = class extends TextHighlightRules {
        constructor() {
          super();
          this.$rules = rules;
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>define([
  'common/collections/user-satisfaction'
],
function (UserSatisfactionCollection) {
  return {

    requiresSvg: true,
    hasDatePicker: true,
    collectionClass: UserSatisfactionCollection,

    collectionOptions: function () {
      return {
        id: 'user_satisfaction',
        title: 'User satisfaction',
        min: 1,
        max: 5,
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute'),
        axisPeriod: this.model.get('axis-period'),
        trim: this.model.get('trim') === false ? false : true,
        format: this.model.get('format') || 'integer',
        axes: _.merge({
          x: {
            label: 'Date',
            key: '_start_at',
            format: 'date'
          },
          y: [
            {
              label: this.model.get('title'),
              key: 'rating',
              format: 'percent'
            },
            {
              label: 'Not satisfied',
              key: 'rating_1:sum',
              format: 'integer'
            },
            {
              label: 'Dissatisfied',
              key: 'rating_2:sum',
              format: 'integer'
            },
            {
              label: 'Neither satisfied or dissatisfied',
              key: 'rating_3:sum',
              format: 'integer'
            },
            {
              label: 'Satisfied',
              key: 'rating_4:sum',
              format: 'integer'
            },
            {
              label: 'Very satisfied',
              key: 'rating_5:sum',
              format: 'integer'
            }
          ]
        }, this.model.get('axes'))
      };
    },

    visualisationOptions: function () {
      return {
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute'),
        formatOptions: this.model.get('format') || 'integer',
        url: this.url
      };
    }

  };
});
<commit_msg>Fix "Very dissatisfied" label on user satisfaction module<commit_after>define([
  'common/collections/user-satisfaction'
],
function (UserSatisfactionCollection) {
  return {

    requiresSvg: true,
    hasDatePicker: true,
    collectionClass: UserSatisfactionCollection,

    collectionOptions: function () {
      return {
        id: 'user_satisfaction',
        title: 'User satisfaction',
        min: 1,
        max: 5,
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute'),
        axisPeriod: this.model.get('axis-period'),
        trim: this.model.get('trim') === false ? false : true,
        format: this.model.get('format') || 'integer',
        axes: _.merge({
          x: {
            label: 'Date',
            key: '_start_at',
            format: 'date'
          },
          y: [
            {
              label: this.model.get('title'),
              key: 'rating',
              format: 'percent'
            },
            {
              label: 'Very dissatisfied',
              key: 'rating_1:sum',
              format: 'integer'
            },
            {
              label: 'Dissatisfied',
              key: 'rating_2:sum',
              format: 'integer'
            },
            {
              label: 'Neither satisfied or dissatisfied',
              key: 'rating_3:sum',
              format: 'integer'
            },
            {
              label: 'Satisfied',
              key: 'rating_4:sum',
              format: 'integer'
            },
            {
              label: 'Very satisfied',
              key: 'rating_5:sum',
              format: 'integer'
            }
          ]
        }, this.model.get('axes'))
      };
    },

    visualisationOptions: function () {
      return {
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute'),
        formatOptions: this.model.get('format') || 'integer',
        url: this.url
      };
    }

  };
});
<|endoftext|>


<commit_before>define([
  'extensions/controllers/module',
  'common/views/visualisations/completion_rate',
  'common/collections/user-satisfaction'
],
function (ModuleController, UserSatisfactionView, UserSatisfactionCollection) {
  var UserSatisfactionModule = ModuleController.extend({
    visualisationClass: UserSatisfactionView,
    collectionClass: UserSatisfactionCollection,
    clientRenderOnInit: true,
    requiresSvg: true,
    collectionOptions: function () {
      return {
        id: 'user_satisfaction',
        title: 'User satisfaction',
        sortBy: '_timestamp:ascending',
        limit: 0,
        min: 1,
        max: 5,
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute'),
        period: this.model.get('period') || 'day',
        duration: this.model.get('duration') || 63,
        trim: this.model.get('trim') || 8,
        axes: _.merge({
          x: {
            label: 'Date',
            key: '_start_at',
            format: 'date'
          },
          y: [
            {
              label: this.model.get('title'),
              key: 'rating',
              format: 'percent'
            }
          ]
        }, this.model.get('axes'))
      };
    },
    visualisationOptions: function () {
      return {
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute')
      };
    }
  });

  return UserSatisfactionModule;
});
<commit_msg>Set default duration of user satisfaction graph to 30 days<commit_after>define([
  'extensions/controllers/module',
  'common/views/visualisations/completion_rate',
  'common/collections/user-satisfaction'
],
function (ModuleController, UserSatisfactionView, UserSatisfactionCollection) {
  var UserSatisfactionModule = ModuleController.extend({
    visualisationClass: UserSatisfactionView,
    collectionClass: UserSatisfactionCollection,
    clientRenderOnInit: true,
    requiresSvg: true,
    collectionOptions: function () {
      return {
        id: 'user_satisfaction',
        title: 'User satisfaction',
        sortBy: '_timestamp:ascending',
        limit: 0,
        min: 1,
        max: 5,
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute'),
        period: this.model.get('period') || 'day',
        duration: this.model.get('duration') || 30,
        trim: this.model.get('trim') || true,
        axes: _.merge({
          x: {
            label: 'Date',
            key: '_start_at',
            format: 'date'
          },
          y: [
            {
              label: this.model.get('title'),
              key: 'rating',
              format: 'percent'
            }
          ]
        }, this.model.get('axes'))
      };
    },
    visualisationOptions: function () {
      return {
        totalAttr: 'totalRatings',
        valueAttr: this.model.get('value-attribute')
      };
    }
  });

  return UserSatisfactionModule;
});
<|endoftext|>


<commit_before>// Next:
// DONE: output cursor: move to end, so that new commands are showing
// get rid of extra newline character so Mike doesn't get offended :(

// get text from line highlihted -> read code
// send only current line
// send on Shift Enter,  I don't think we are able to catch Shift-enter :(
//

// resize text area (happens automatically? in Safari) -> set textWidth to width of textarea, whenever user resizes the area (and in the beginning)
// horizontal scroll bar, so text doesn't wrap
// only send current line from text input
// keep history of input
// print output once it's back instead of hitting enter over and over, global
// event handler?
// handle post callback differently. Ajax?
// make a good keyboard for iPad
// textarea in Safari is hard to read because of shadows

$(document).ready(function() {

		// initialisation
		editAreaLoader.init({
			id: "M2In"	// id of the textarea to transform
			,start_highlight: true	// if start with highlight
			,allow_resize: "both"
			,allow_toggle: false
			,word_wrap: false
			,language: "en"
			,syntax: "php"
		});

		editAreaLoader.init({
			id: "M2Out"	// id of the textarea to transform
			,start_highlight: true	// if start with highlight
			,allow_resize: "both"
			,allow_toggle: false
			,word_wrap: false
			,language: "en"
			,syntax: "php"
		});

		// callback functions

		function test_setSelectionRange(id){
			editAreaLoader.setSelectionRange(id, 100, 150);
		}

		function test_getSelectionRange(id){
			var sel =editAreaLoader.getSelectionRange(id);
			("start: "+sel["start"]+"\nend: "+sel["end"]);
		}

		function test_setSelectedText(id){
			text= "[REPLACED SELECTION]";
			editAreaLoader.setSelectedText(id, text);
		}

		function test_getSelectedText(id){
			alert(editAreaLoader.getSelectedText(id));
		}

		function toogle_editable(id)
		{
			editAreaLoader.execCommand(id, 'set_editable', !editAreaLoader.execCommand(id, 'is_editable'));
		}

		function con_keys(e){
			alert('enter!');
		}

				addEvent("M2In",'keypress',con_keys);

  // add markup to container and apply click handlers to anchors
  //$("#header a").click(function(e) {

  $('#textarea').keypress(function(e) {
	alert('enter!');
    if(e.which == 13){

      submitNow();
    }
  });

  $("#button1").click(submitNow);

  $("#reset").click(function(e) {
    if (!sendToM2( ">>RESET<<", "We are resetting the current M2 session.\n")) {
      $("#M2Out").val($("#M2Out").val() + "Something Broke! HELP!");
    }
    $("#M2Out").val("");
  });

  //$("#M2Out").append(window.getSelected());
  //$("#M2Out").val($("#M2Out").val() + "\n");
});

// return false on error
function sendToM2( myCommand, baseString ) {
  $.post("sockets/M2Client.php", {cmd: myCommand}, function(data){
    if(data != "0") {
		//alert ('-' + data + '-');
		editAreaLoader.setValue("M2Out", baseString + data)
    //  $("#M2Out").val(baseString + data );
		scrollDown();
      $("#M2In").val("");
    } else {
      return false;
    }
  });
  return true;
}

/* attempt to find a text selection */
function getSelected() {
  if(window.getSelection) { $('#M2Out').append("Get Selected! option1\n --" + window.getSelection() + "--"); return window.getSelection();  }

  else if(document.getSelection) { $('#M2Out').append("option2");return document.getSelection(); }
  else {
    var selection = document.selection && document.selection.createRange();
    if(selection.text) { $('#M2Out').append("option3"); return selection.text; }
    $('#M2Out').append("option4");
    return false;
  }
  $('#M2Out').append("option never");
  return false;
}

function scrollDown() {
	mySize = $('#M2Out').val().length;
	//$t.animate({ scrollTop: mySize}, 1000);
	//$("#M2Out").val($("#M2Out").val() + "\nSize: " + mySize);
	$('#M2Out').scrollTop(mySize);
	//animate({scrollTop: 0},'slow');
	return false; // Return false to cancel the default link action
}

function submitNow(e) {
  var myCommand;
  var sel = editAreaLoader.getSelectionRange("M2In");
  var str = editAreaLoader.getValue("M2In");
  if (sel["start"] == sel["end"]) {
    // grab the current line
    sel["start"] = 1 + str.lastIndexOf("\n", sel["end"]-1);

	var endPos = str.indexOf("\n", sel["start"]);
	if ( endPos != -1) {
		sel["end"] = endPos;
	} else {
		sel["end"] = str.length;
		//alert ("last line");

	}
  }

  //alert("start: "+sel["start"]+"\nend: "+sel["end"]);
  myCommand = str.slice(sel["start"],sel["end"]) + "\n";
  //alert("command: \n" + myCommand);

  // call to php script
  if (!sendToM2( myCommand, "Session initialized successfully! ")) {
    $("#M2Out").val($("#M2Out").val() + "Something Broke! HELP!");
  }
}

/* create sniffer */
/*$(document).ready(function() {
  $('#content-area').mouseup(function() {
  var selection = getSelected();
  if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,''))) {
  $.ajax({
type: 'post',
url: 'ajax-selection-copy.php',
data: 'selection=' + encodeURI(selection)
});
}
});
});*/

<commit_msg>somehow this is working right now<commit_after>// Next:
// DONE: output cursor: move to end, so that new commands are showing
// get rid of extra newline character so Mike doesn't get offended :(

// get text from line highlihted -> read code
// send only current line
// send on Shift Enter,  I don't think we are able to catch Shift-enter :(
//

// resize text area (happens automatically? in Safari) -> set textWidth to width of textarea, whenever user resizes the area (and in the beginning)
// horizontal scroll bar, so text doesn't wrap
// only send current line from text input
// keep history of input
// print output once it's back instead of hitting enter over and over, global
// event handler?
// handle post callback differently. Ajax?
// make a good keyboard for iPad
// textarea in Safari is hard to read because of shadows

$(document).ready(function() {

		// initialisation
		editAreaLoader.init({
			id: "M2In"	// id of the textarea to transform
			,start_highlight: true	// if start with highlight
			,allow_resize: "both"
			,allow_toggle: false
			,word_wrap: false
			,language: "en"
			,syntax: "php"
		});

		editAreaLoader.init({
			id: "M2Out"	// id of the textarea to transform
			,start_highlight: true	// if start with highlight
			,allow_resize: "both"
			,allow_toggle: false
			,word_wrap: false
			,language: "en"
			,syntax: "php"
		});

		// callback functions

		function test_setSelectionRange(id){
			editAreaLoader.setSelectionRange(id, 100, 150);
		}

		function test_getSelectionRange(id){
			var sel =editAreaLoader.getSelectionRange(id);
			("start: "+sel["start"]+"\nend: "+sel["end"]);
		}

		function test_setSelectedText(id){
			text= "[REPLACED SELECTION]";
			editAreaLoader.setSelectedText(id, text);
		}

		function test_getSelectedText(id){
			alert(editAreaLoader.getSelectedText(id));
		}

		function toogle_editable(id)
		{
			editAreaLoader.execCommand(id, 'set_editable', !editAreaLoader.execCommand(id, 'is_editable'));
		}

  // add markup to container and apply click handlers to anchors
  //$("#header a").click(function(e) {

  $('#textarea').keypress(function(e) {
	alert('enter!');
    if(e.which == 13){

      submitNow();
    }
  });

  $("#button1").click(submitNow);

  $("#reset").click(function(e) {
    if (!sendToM2( ">>RESET<<", "We are resetting the current M2 session.\n")) {
      $("#M2Out").val($("#M2Out").val() + "Something Broke! HELP!");
    }
    $("#M2Out").val("");
  });

  //$("#M2Out").append(window.getSelected());
  //$("#M2Out").val($("#M2Out").val() + "\n");
});

// return false on error
function sendToM2( myCommand, baseString ) {
  $.post("sockets/M2Client.php", {cmd: myCommand}, function(data){
    if(data != "0") {
		//alert ('-' + data + '-');
		editAreaLoader.setValue("M2Out", baseString + data)
    //  $("#M2Out").val(baseString + data );
		scrollDown();
      $("#M2In").val("");
    } else {
      return false;
    }
  });
  return true;
}

/* attempt to find a text selection */
function getSelected() {
  if(window.getSelection) { $('#M2Out').append("Get Selected! option1\n --" + window.getSelection() + "--"); return window.getSelection();  }

  else if(document.getSelection) { $('#M2Out').append("option2");return document.getSelection(); }
  else {
    var selection = document.selection && document.selection.createRange();
    if(selection.text) { $('#M2Out').append("option3"); return selection.text; }
    $('#M2Out').append("option4");
    return false;
  }
  $('#M2Out').append("option never");
  return false;
}

function scrollDown() {
	mySize = $('#M2Out').val().length;
	//$t.animate({ scrollTop: mySize}, 1000);
	//$("#M2Out").val($("#M2Out").val() + "\nSize: " + mySize);
	$('#M2Out').scrollTop(mySize);
	//animate({scrollTop: 0},'slow');
	return false; // Return false to cancel the default link action
}

function submitNow(e) {
  var myCommand;
  var sel = editAreaLoader.getSelectionRange("M2In");
  var str = editAreaLoader.getValue("M2In");
  if (sel["start"] == sel["end"]) {
    // grab the current line
    sel["start"] = 1 + str.lastIndexOf("\n", sel["end"]-1);

	var endPos = str.indexOf("\n", sel["start"]);
	if ( endPos != -1) {
		sel["end"] = endPos;
	} else {
		sel["end"] = str.length;
		//alert ("last line");

	}
  }

  //alert("start: "+sel["start"]+"\nend: "+sel["end"]);
  myCommand = str.slice(sel["start"],sel["end"]) + "\n";
  //alert("command: \n" + myCommand);

  // call to php script
  if (!sendToM2( myCommand, "Session initialized successfully! ")) {
    $("#M2Out").val($("#M2Out").val() + "Something Broke! HELP!");
  }
}

/* create sniffer */
/*$(document).ready(function() {
  $('#content-area').mouseup(function() {
  var selection = getSelected();
  if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,''))) {
  $.ajax({
type: 'post',
url: 'ajax-selection-copy.php',
data: 'selection=' + encodeURI(selection)
});
}
});
});*/

<|endoftext|>


<commit_before>/**
 * @module timed
 * @submodule timed-components
 * @public
 */
import Component       from 'ember-component'
import computed        from 'ember-computed-decorators'
import moment          from 'moment'
import formatDuration  from 'timed/utils/format-duration'
import { padStartTpl } from 'ember-pad/utils/pad'
import { htmlSafe }    from 'ember-string'

const padTpl2 = padStartTpl(2)

/**
 * The formatter for the slider tooltips
 *
 * @constant
 * @type {Object}
 * @public
 */
const Formatter = {
  /**
   * Format the minutes to a time string
   *
   * @method to
   * @param {Number} value The time in minutes
   * @return {String} The formatted time
   * @public
   */
  to(value) {
    return moment({ hour: 0 }).minute(value).format('HH:mm')
  }
}

/**
 * The attendance slider component
 *
 * @class AttendanceSliderComponent
 * @extends Ember.Component
 * @public
 */
export default Component.extend({
  /**
   * The attendance
   *
   * @property {Attendance} attendance
   * @public
   */
  attendance: null,

  /**
   * Initialize the component
   *
   * @method init
   * @public
   */
  init() {
    this._super(...arguments)

    this.set('tooltips', [ Formatter, Formatter ])
    this.set('values', this.get('start'))
  },

  /**
   * The start and end time in minutes
   *
   * @property {Number[]} start
   * @public
   */
  @computed('attendance.{from,to}')
  start(from, to) {
    return [
      from.hour() * 60 + from.minute(),
      to.hour() * 60 + to.minute()
    ]
  },

  /**
   * The duration of the attendance as a string
   *
   * @property {String} duration
   * @public
   */
  @computed('values')
  duration([ fromMin, toMin ]) {
    let from = moment({ hour: 0 }).minute(fromMin)
    let to   = moment({ hour: 0 }).minute(toMin)

    return formatDuration(moment.duration(to.diff(from)), false)
  },

  /**
   * The labels for the slider
   *
   * @property {String[]} labels
   * @public
   */
  @computed
  labels() {
    let labels = []

    for (let h = 0; h <= 24; h++) {
      for (let m = 0; m <= 30 && !(h === 24 && m === 30); m += 30) {
        let offsetH = 100 / 24 * h
        let offsetM = 100 / 24 / 60 * m

        labels.push({
          value: padTpl2`${h}:${m}`,
          size: m === 0 ? 'lg' : 'sm',
          style: htmlSafe(`left: ${offsetH + offsetM}%;`)
        })
      }
    }

    return labels
  },

  /**
   * The actions of the attendance slider component
   *
   * @property {Object} actions
   * @public
   */
  actions: {
    /**
     * Save the attendance
     *
     * @method save
     * @param {Number[]} values The time in minutes
     * @public
     */
    save([ fromMin, toMin ]) {
      this.set('attendance.from', moment({ hour: 0 }).minute(fromMin))
      this.set('attendance.to', moment({ hour: 0 }).minute(toMin))

      this.get('attrs.on-save')(this.get('attendance'))
    },

    /**
     * Delete the attendance
     *
     * @method delete
     * @public
     */
    delete() {
      this.get('attrs.on-delete')(this.get('attendance'))
    }
  }
})
<commit_msg>Fixed editing of a past attendance<commit_after>/**
 * @module timed
 * @submodule timed-components
 * @public
 */
import Component       from 'ember-component'
import computed        from 'ember-computed-decorators'
import moment          from 'moment'
import formatDuration  from 'timed/utils/format-duration'
import { padStartTpl } from 'ember-pad/utils/pad'
import { htmlSafe }    from 'ember-string'

const padTpl2 = padStartTpl(2)

/**
 * The formatter for the slider tooltips
 *
 * @constant
 * @type {Object}
 * @public
 */
const Formatter = {
  /**
   * Format the minutes to a time string
   *
   * @method to
   * @param {Number} value The time in minutes
   * @return {String} The formatted time
   * @public
   */
  to(value) {
    return moment({ hour: 0 }).minute(value).format('HH:mm')
  }
}

/**
 * The attendance slider component
 *
 * @class AttendanceSliderComponent
 * @extends Ember.Component
 * @public
 */
export default Component.extend({
  /**
   * The attendance
   *
   * @property {Attendance} attendance
   * @public
   */
  attendance: null,

  /**
   * Initialize the component
   *
   * @method init
   * @public
   */
  init() {
    this._super(...arguments)

    this.set('tooltips', [ Formatter, Formatter ])
    this.set('values', this.get('start'))
  },

  /**
   * The start and end time in minutes
   *
   * @property {Number[]} start
   * @public
   */
  @computed('attendance.{from,to}')
  start(from, to) {
    return [
      from.hour() * 60 + from.minute(),
      to.hour() * 60 + to.minute()
    ]
  },

  /**
   * The duration of the attendance as a string
   *
   * @property {String} duration
   * @public
   */
  @computed('values')
  duration([ fromMin, toMin ]) {
    let from = moment({ hour: 0 }).minute(fromMin)
    let to   = moment({ hour: 0 }).minute(toMin)

    return formatDuration(moment.duration(to.diff(from)), false)
  },

  /**
   * The labels for the slider
   *
   * @property {String[]} labels
   * @public
   */
  @computed
  labels() {
    let labels = []

    for (let h = 0; h <= 24; h++) {
      for (let m = 0; m <= 30 && !(h === 24 && m === 30); m += 30) {
        let offsetH = 100 / 24 * h
        let offsetM = 100 / 24 / 60 * m

        labels.push({
          value: padTpl2`${h}:${m}`,
          size: m === 0 ? 'lg' : 'sm',
          style: htmlSafe(`left: ${offsetH + offsetM}%;`)
        })
      }
    }

    return labels
  },

  /**
   * The actions of the attendance slider component
   *
   * @property {Object} actions
   * @public
   */
  actions: {
    /**
     * Save the attendance
     *
     * @method save
     * @param {Number[]} values The time in minutes
     * @public
     */
    save([ fromMin, toMin ]) {
      let attendance = this.get('attendance')

      attendance.set('from', moment(attendance.get('from')).hour(0).minute(fromMin))
      attendance.set('to', moment(attendance.get('to')).hour(0).minute(toMin))

      this.get('attrs.on-save')(attendance)
    },

    /**
     * Delete the attendance
     *
     * @method delete
     * @public
     */
    delete() {
      this.get('attrs.on-delete')(this.get('attendance'))
    }
  }
})
<|endoftext|>


<commit_before>function GF2 ()
{
	var a = new Micma ()
	a.lut["*"] = [[0,0],[0,1]]
	a.lut["+"] = [[0,1],[1,0]]
	return a
}

function MinMax4 ()
{
	var a = new Micma ()
	{
		a.lut ["&"] = [[0,0,0,0],[0,1,1,1],[0,1,2,2],[0,1,2,3]]
		a.lut ["|"] = [[0,1,2,3],[1,1,2,3],[2,2,2,3],[3,3,3,3]]
	}
	return a
}

function RockPaperScizzors ()
{
	var a = new Micma ()
	{
		a.lut ["W"] = [[0,1,0],[1,1,2],[0,2,2]]
		a.lut ["L"] = [[0,0,2],[0,1,1],[0,2,2]]
	}
	return a
}

function Imply ()
{
	var a = new Micma ()
	{
		a.lut["<"] = [[1,0],[1,1]]
		a.lut[">"] = [[1,1],[0,1]]
	}
	return a
}

function gf2test ()
{
	var gf2 = GF2 ()
	var preterm = [1,1,"+",1, 1,"*"]
	var term = new Term (preterm,gf2)
	return term.evaluate()
}

function underflowTest ()  //does strange things, not sure if i care
{
	var gf2 = GF2 ()
	var preterm = [1,"+"]
	var term = new Term (preterm,gf2)
	return term.evaluate ()
}

function isCommutative (micma, op, limit)
{
	var term = new Term (["a","b",op,"b","a",op], micma)
	var query = new Query (["aA","bA"], limit, term)
	return query.evaluate ()
}

function isAssociative (micma, op, limit)
{
	var term = new Term (["a","b","c",op,op,"a","b",op,"c",op], micma)
	var query = new Query (["aA","bA","cA"], limit, term)
	return query.evaluate ()
}

function commTest ()
{
	alert (isCommutative (MinMax4(), "&", 4))
	alert (isCommutative (RockPaperScizzors(), "W", 3))
	alert (isCommutative (Imply()), ">", 2)

	alert (isAssociative (MinMax4(), "&", 4))
	alert (isAssociative  (RockPaperScizzors(), "W", 3))
	alert (isAssociative  (Imply()), ">", 2)
}
<commit_msg>turns out, my test function was broken XD<commit_after>function GF2 ()
{
	var a = new Micma ()
	a.lut["*"] = [[0,0],[0,1]]
	a.lut["+"] = [[0,1],[1,0]]
	return a
}

function MinMax4 ()
{
	var a = new Micma ()
	{
		a.lut ["&"] = [[0,0,0,0],[0,1,1,1],[0,1,2,2],[0,1,2,3]]
		a.lut ["|"] = [[0,1,2,3],[1,1,2,3],[2,2,2,3],[3,3,3,3]]
	}
	return a
}

function RockPaperScizzors ()
{
	var a = new Micma ()
	{
		a.lut ["W"] = [[0,1,0],[1,1,2],[0,2,2]]
		a.lut ["L"] = [[0,0,2],[0,1,1],[0,2,2]]
	}
	return a
}

function Imply ()
{
	var a = new Micma ()
	{
		a.lut["<"] = [[1,0],[1,1]]
		a.lut[">"] = [[1,1],[0,1]]
	}
	return a
}

function gf2test ()
{
	var gf2 = GF2 ()
	var preterm = [1,1,"+",1, 1,"*"]
	var term = new Term (preterm,gf2)
	return term.evaluate()
}

function underflowTest ()  //does strange things, not sure if i care
{
	var gf2 = GF2 ()
	var preterm = [1,"+"]
	var term = new Term (preterm,gf2)
	return term.evaluate ()
}

function isCommutative (micma, op, limit)
{
	var term = new Term (["a","b",op,"b","a",op], micma)
	var query = new Query (["aA","bA"], limit, term)
	return query.evaluate ()
}

function isAssociative (micma, op, limit)
{
	var term = new Term (["a","b","c",op,op,"a","b",op,"c",op], micma)
	var query = new Query (["aA","bA","cA"], limit, term)
	return query.evaluate ()
}

function commTest ()
{
	return [
		isCommutative (MinMax4(), "&", 4),
		isCommutative (RockPaperScizzors(), "W", 3),
		isCommutative (Imply(), ">", 2),

		isAssociative (MinMax4(), "&", 4),
		isAssociative (RockPaperScizzors(), "W", 3),
		isAssociative (Imply(), ">", 2)
	]
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  errorHandler = require('./errors.server.controller'),
  _ = require('lodash'),
  async = require('async'),
  Transaction = mongoose.model('Transaction'),
  User = mongoose.model('User');

exports.list = function (req, res) {
  Transaction.aggregate()
    .match({
      '$or': [
        { user: req.user._id },
        { friend: req.user._id }
      ],
      status: { $nin: ['paid', 'revoked'] }
    })
    .group({
      _id: {
        friend: {
          $cond: [
            { $eq: ['$friend', req.user._id] },
            '$user',
            { $ifNull: ['$friend', '$to'] }
          ]
        }
      },
      total: {
        $sum: {
          $cond: [
            {
              $or: [
                { $and: [
                  { $eq: ['$user', req.user._id] },
                  { $eq: ['$kind', 'receive'] }
                ]},
                { $and: [
                  { $eq: ['$friend', req.user._id] },
                  { $eq: ['$kind', 'pay'] }
                ]}
              ]
            },
            '$value',
            { $multiply: ['$value', -1] }
          ]
        }
      },
      average: { $avg: '$value' },
      count: { $sum: 1 }
    })
    .exec(function (err, result) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        var payables = [];

        async.each(result, function (payable, done) {
          User.findById(payable._id.friend).select('id displayName').exec(function (err, friend) {
            if (friend) {
              payable._id.to = friend.displayName;
            } else {
              payable._id.to = payable._id.friend;
            }
            payables.push(payable);
            done();
          });
        }, function (err) {
          res.jsonp(payables);
        });

      }
    });
};
<commit_msg>Update payables.server.controller.js<commit_after>'use strict';

/**
 * Module dependencies.
 */
var mongoose = require('mongoose'),
  errorHandler = require('./errors.server.controller'),
  _ = require('lodash'),
  async = require('async'),
  Transaction = mongoose.model('Transaction'),
  User = mongoose.model('User');

exports.list = function (req, res) {
  Transaction.aggregate()
    .match({
      '$or': [
        { user: req.user._id },
        { friend: req.user._id }
      ],
      status: { $nin: ['paid', 'revoked'] }
    })
    .group({
      _id: {
        friend: {
          $cond: [
            { $eq: ['$friend', req.user._id] },
            '$user',
            { $ifNull: ['$friend', '$to'] }
          ]
        }
      },
      total: {
        $sum: {
          $cond: [
            {
              $or: [
                { $and: [
                  { $eq: ['$user', req.user._id] },
                  { $eq: ['$kind', 'receive'] }
                ]},
                { $and: [
                  { $eq: ['$friend', req.user._id] },
                  { $eq: ['$kind', 'pay'] }
                ]}
              ]
            },
            '$value',
            { $multiply: ['$value', -1] }
          ]
        }
      },
      average: { $avg: '$value' },
      count: { $sum: 1 }
    })
    .exec(function (err, result) {
      if (err) {
        return res.status(400).send({
          message: errorHandler.getErrorMessage(err)
        });
      } else {
        var payables = [];

        async.each(result, function (payable, done) {
          // horrivel!
          User.findById(payable._id.friend).select('id displayName').exec(function (err, friend) {
            if (friend) {
              payable._id.to = friend.displayName;
            } else {
              payable._id.to = payable._id.friend;
            }
            payables.push(payable);
            done();
          });
        }, function (err) {
          res.jsonp(payables);
        });

      }
    });
};
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var qs = require('./');

var obj = qs.parse('foo');
require('inspect')(obj)

var obj = qs.parse('foo=bar=baz');
require('inspect')(obj)

var obj = qs.parse('users[]');
require('inspect')(obj)

var obj = qs.parse('name=tj&email=tj@vision-media.ca');
require('inspect')(obj)

var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
require('inspect')(obj)

var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
require('inspect')(obj)

var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
require('inspect')(obj)<commit_msg>more examples<commit_after>
/**
 * Module dependencies.
 */

var qs = require('./');

var obj = qs.parse('foo');
require('inspect')(obj)

var obj = qs.parse('foo=bar=baz');
require('inspect')(obj)

var obj = qs.parse('users[]');
require('inspect')(obj)

var obj = qs.parse('name=tj&email=tj@vision-media.ca');
require('inspect')(obj)

var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane');
require('inspect')(obj)

var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk');
require('inspect')(obj)

var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk');
require('inspect')(obj)

var obj = qs.parse('a=a&a=b&a=c');
require('inspect')(obj)

var obj = qs.parse('user[tj]=tj&user[tj]=TJ');
require('inspect')(obj)
<|endoftext|>