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

/*
  Determine Basal

  Released under MIT license. See the accompanying LICENSE.txt file for
  full terms and conditions

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

function getLastGlucose(data) {

    var now = data[0];
    var last = data[1];
    var avg;
    //TODO: calculate average using system_time instead of assuming 1 data point every 5m
    if (typeof data[3] !== 'undefined' && data[3].glucose > 30) {
        avg = ( now.glucose - data[3].glucose) / 3;
    } else if (typeof data[2] !== 'undefined' && data[2].glucose > 30) {
        avg = ( now.glucose - data[2].glucose) / 2;
    } else if (typeof data[1] !== 'undefined' && data[1].glucose > 30) {
        avg = now.glucose - data[1].glucose;
    } else { avg = 0; }
    var o = {
        delta: now.glucose - last.glucose
        , glucose: now.glucose
        , avgdelta: avg
    };

    return o;

}

function setTempBasal(rate, duration) {

    maxSafeBasal = Math.min(profile_data.max_basal, 3 * profile_data.max_daily_basal, 4 * profile_data.current_basal);

    if (rate < 0) { rate = 0; } // if >30m @ 0 required, zero temp will be extended to 30m instead
    else if (rate > maxSafeBasal) { rate = maxSafeBasal; }

    // rather than canceling temps, if Offline mode is set, always set the current basal as a 30m temp
    // so we can see on the pump that openaps is working
    if (duration == 0 && offline_input == 'Offline') {
        rate = profile_data.current_basal;
        duration  = 30;
    }

    requestedTemp.duration = duration;
    requestedTemp.rate = Math.round((Math.round(rate / 0.05) * 0.05)*100)/100;
};

if (!module.parent) {
    var iob_input = process.argv.slice(2, 3).pop()
    var temps_input = process.argv.slice(3, 4).pop()
    var glucose_input = process.argv.slice(4, 5).pop()
    var profile_input = process.argv.slice(5, 6).pop()
    var offline_input = process.argv.slice(6, 7).pop()

    if (!iob_input || !temps_input || !glucose_input || !profile_input) {
        console.error('usage: ', process.argv.slice(0, 2), '<iob.json> <current-temps.json> <glucose.json> <profile.json> [Offline]');
        process.exit(1);
    }

    var cwd = process.cwd()
    var glucose_data = require(cwd + '/' + glucose_input);
    var temps_data = require(cwd + '/' + temps_input);
    var iob_data = require(cwd + '/' + iob_input);
    var profile_data = require(cwd + '/' + profile_input);

    if (typeof profile_data === 'undefined' || typeof profile_data.current_basal === 'undefined') {
        console.error('Error: could not get current basal rate');
        process.exit(1);
    }

    var max_iob = profile_data.max_iob; // maximum amount of non-bolus IOB OpenAPS will ever deliver

    // if target_bg is set, great. otherwise, if min and max are set, then set target to their average
    var target_bg;
    if (typeof profile_data.target_bg !== 'undefined') {
        target_bg = profile_data.target_bg;
    } else {
        if (typeof profile_data.max_bg !== 'undefined' && typeof profile_data.max_bg !== 'undefined') {
            target_bg = (profile_data.min_bg + profile_data.max_bg) / 2;
        } else {
            console.error('Error: could not determine target_bg');
            process.exit(1);
        }
    }

    var glucose_status = getLastGlucose(glucose_data);
    var bg = glucose_status.glucose;
    var tick;
    if (glucose_status.delta >= 0) { tick = "+" + glucose_status.delta; }
    else { tick = glucose_status.delta; }
    console.error("IOB: " + iob_data.iob.toFixed(2) + ", Bolus IOB: " + iob_data.bolusiob.toFixed(2));
    //calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
    var bgi = -iob_data.activity * profile_data.sens * 5;
    console.error("Avg. Delta: " + glucose_status.avgdelta.toFixed(1) + ", BGI: " + bgi.toFixed(1));
    // project deviation over next 15 minutes
    var deviation = Math.round( 15 / 5 * ( glucose_status.avgdelta - bgi ) );
    console.error("15m deviation: " + deviation.toFixed(0));
    // calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
    var naive_eventualBG = Math.round( bg - (iob_data.iob * profile_data.sens) );
    // and adjust it for the deviation above
    var eventualBG = naive_eventualBG + deviation;
    // calculate what portion of that is due to bolusiob
    var bolusContrib = iob_data.bolusiob * profile_data.sens;
    // and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
    var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
    // adjust that for deviation like we did eventualBG
    var snoozeBG = naive_snoozeBG + deviation;
    console.error("BG: " + bg + tick + " -> " + eventualBG + "-" + snoozeBG + " (Unadjusted: " + naive_eventualBG + "-" + naive_snoozeBG + ")");
    if (typeof eventualBG === 'undefined') { console.error('Error: could not calculate eventualBG'); }
    var requestedTemp = {
        'temp': 'absolute'
        , 'bg': bg
        , 'tick': tick
        , 'eventualBG': eventualBG
        , 'snoozeBG': snoozeBG
    };

    //if old reading from Dexcom do nothing

    var systemTime = new Date();
    var bgTime;
    if (glucose_data[0].display_time) {
        bgTime = new Date(glucose_data[0].display_time.replace('T', ' '));
    } else if (glucose_data[0].dateString) {
        bgTime = new Date(glucose_data[0].dateString);
    } else { console.error("Could not determine last BG time"); }
    var minAgo = (systemTime - bgTime) / 60 / 1000
    var threshold = profile_data.min_bg - 30;
    var reason="";

    if (minAgo < 10 && minAgo > -5) { // Dexcom data is recent, but not far in the future

        if (bg > 10) {  //Dexcom is in ??? mode or calibrating, do nothing. Asked @benwest for raw data in iter_glucose

            if (bg < threshold) { // low glucose suspend mode: BG is < ~80
                reason = "BG " + bg + "<" + threshold;
                console.error(reason);
                if (glucose_status.delta > 0) { // if BG is rising
                    if (temps_data.rate > profile_data.current_basal) { // if a high-temp is running
                        setTempBasal(0, 0); // cancel high temp
                    } else if (temps_data.duration && eventualBG > profile_data.max_bg) { // if low-temped and predicted to go high from negative IOB
                        setTempBasal(0, 0); // cancel low temp
                    } else {
                        reason = bg + "<" + threshold + "; no high-temp to cancel";
                        console.error(reason);
                    }
                }
                else { // BG is not yet rising
                    setTempBasal(0, 30);
                }

            } else {

                // if BG is rising but eventual BG is below min, or BG is falling but eventual BG is above min
                if ((glucose_status.delta > 0 && eventualBG < profile_data.min_bg) || (glucose_status.delta < 0 && eventualBG >= profile_data.min_bg)) {
                    if (temps_data.duration > 0) { // if there is currently any temp basal running
                        // if it's a low-temp and eventualBG < profile_data.max_bg, let it run a bit longer
                        if (temps_data.rate <= profile_data.current_basal && eventualBG < profile_data.max_bg) {
                            reason = "BG" + tick + " but eventualBG " + eventualBG + "<" + profile_data.max_bg;
                            console.error(reason);
                        } else {
                            reason = tick + " and eventualBG " + eventualBG;
                            setTempBasal(0, 0); // cancel temp
                        }
                    } else {
                        reason = tick + "; no temp to cancel";
                        console.error(reason);
                    }

                } else if (eventualBG < profile_data.min_bg) { // if eventual BG is below target:
                    // if this is just due to boluses, we can snooze until the bolus IOB decays (at double speed)
                    if (snoozeBG > profile_data.min_bg) { // if adding back in the bolus contribution BG would be above min
                        // if BG is falling and high-temped, or rising and low-temped, cancel
                        if (glucose_status.delta < 0 && temps_data.rate > profile_data.current_basal) {
                            reason = tick + " and temp " + temps_data.rate + " > basal " + profile_data.current_basal;
                            setTempBasal(0, 0); // cancel temp
                        } else if (glucose_status.delta > 0 && temps_data.rate < profile_data.current_basal) {
                            reason = tick + " and temp " + temps_data.rate + " < basal " + profile_data.current_basal;
                            setTempBasal(0, 0); // cancel temp
                        } else {
                            reason = "bolus snooze: eventual BG range " + eventualBG + "-" + snoozeBG;
                            console.error(reason);
                        }
                    } else {
                        // calculate 30m low-temp required to get projected BG up to target
                        // negative insulin required to get up to min:
                        //var insulinReq = Math.max(0, (target_bg - eventualBG) / profile_data.sens);
                        // use snoozeBG instead of eventualBG to more gradually ramp in any counteraction of the user's boluses
                        var insulinReq = Math.min(0, (snoozeBG - target_bg) / profile_data.sens);
                        // rate required to deliver insulinReq less insulin over 30m:
                        var rate = profile_data.current_basal + (2 * insulinReq);
                        rate = Math.round( rate * 1000 ) / 1000;
                        // if required temp < existing temp basal
                        if (typeof temps_data.rate !== 'undefined' && (temps_data.duration > 0 && rate > temps_data.rate - 0.1)) {
                            reason = "temp " + temps_data.rate + " <~ req " + rate + "U/hr";
                            console.error(reason);
                        } else {
                            reason = "Eventual BG " + eventualBG + "<" + profile_data.min_bg;
                            //console.error(reason);
                            setTempBasal(rate, 30);
                        }
                    }

                } else if (eventualBG > profile_data.max_bg) { // if eventual BG is above target:
                    // if iob is over max, just cancel any temps
                    var basal_iob = Math.round(( iob_data.iob - iob_data.bolusiob )*1000)/1000;
                    if (basal_iob > max_iob) {
                        reason = "basal_iob " + basal_iob + " > max_iob " + max_iob;
                        setTempBasal(0, 0);
                    } else {
                        // calculate 30m high-temp required to get projected BG down to target
                        // additional insulin required to get down to max bg:
                        var insulinReq = (eventualBG - target_bg) / profile_data.sens;
                        // if that would put us over max_iob, then reduce accordingly
                        if (insulinReq > max_iob-basal_iob) {
                            reason = "max_iob " + max_iob + ", ";
                            insulinReq = max_iob-basal_iob;
                        }

                        // rate required to deliver insulinReq more insulin over 30m:
                        var rate = profile_data.current_basal + (2 * insulinReq);
                        rate = Math.round( rate * 1000 ) / 1000;

                        maxSafeBasal = Math.min(profile_data.max_basal, 3 * profile_data.max_daily_basal, 4 * profile_data.current_basal);
                        if (rate > maxSafeBasal) {
                            rate = maxSafeBasal;
                            //console.error(maxSafeBasal);
                        }
                        var insulinScheduled = temps_data.duration * (temps_data.rate - profile_data.current_basal) / 60;
                        if (insulinScheduled > insulinReq + 0.3) { // if current temp would deliver >0.3U more than the required insulin, lower the rate
                            reason = temps_data.duration + "@" + temps_data.rate + " > req " + insulinReq + "U";
                            setTempBasal(rate, 30);
                        }
                        else if (typeof temps_data.rate == 'undefined' || temps_data.rate == 0) { // no temp is set
                            reason += "no temp, setting " + rate + "U/hr";
                            setTempBasal(rate, 30);
                        }
                        else if (temps_data.duration > 0 && rate < temps_data.rate + 0.1) { // if required temp <~ existing temp basal
                            reason += "temp " + temps_data.rate + " >~ req " + rate + "U/hr";
                            console.error(reason);
                        } else { // required temp > existing temp basal
                            reason += "temp " + temps_data.rate + "<" + rate + "U/hr";
                            setTempBasal(rate, 30);
                        }
                    }

                } else {
                    reason = eventualBG + " is in range. No temp required.";
                    if (temps_data.duration > 0) { // if there is currently any temp basal running
                        setTempBasal(0, 0); // cancel temp
                    } else {
                        console.error(reason);
                    }
                }
            }

            if (offline_input == 'Offline') {
                // if no temp is running or required, set the current basal as a temp, so you can see on the pump that the loop is working
                if ((!temps_data.duration || (temps_data.rate == profile_data.current_basal)) && !requestedTemp.duration) {
                    reason = reason + "; setting current basal of " + profile_data.current_basal + " as temp";
                    setTempBasal(profile_data.current_basal, 30);
                }
            }
        }  else {
            reason = "CGM is calibrating or in ??? state";
            console.error(reason);
        }
    } else {
        reason = "BG data is too old, or clock set incorrectly";
        console.error(reason);
    }

requestedTemp.reason = reason;
console.log(JSON.stringify(requestedTemp));
}
<commit_msg>return requestedTemp<commit_after>#!/usr/bin/env node

/*
  Determine Basal

  Released under MIT license. See the accompanying LICENSE.txt file for
  full terms and conditions

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
*/

function getLastGlucose(data) {

    var now = data[0];
    var last = data[1];
    var avg;
    //TODO: calculate average using system_time instead of assuming 1 data point every 5m
    if (typeof data[3] !== 'undefined' && data[3].glucose > 30) {
        avg = ( now.glucose - data[3].glucose) / 3;
    } else if (typeof data[2] !== 'undefined' && data[2].glucose > 30) {
        avg = ( now.glucose - data[2].glucose) / 2;
    } else if (typeof data[1] !== 'undefined' && data[1].glucose > 30) {
        avg = now.glucose - data[1].glucose;
    } else { avg = 0; }
    var o = {
        delta: now.glucose - last.glucose
        , glucose: now.glucose
        , avgdelta: avg
    };

    return o;

}

function setTempBasal(rate, duration) {

    maxSafeBasal = Math.min(profile_data.max_basal, 3 * profile_data.max_daily_basal, 4 * profile_data.current_basal);

    if (rate < 0) { rate = 0; } // if >30m @ 0 required, zero temp will be extended to 30m instead
    else if (rate > maxSafeBasal) { rate = maxSafeBasal; }

    // rather than canceling temps, if Offline mode is set, always set the current basal as a 30m temp
    // so we can see on the pump that openaps is working
    if (duration == 0 && offline_input == 'Offline') {
        rate = profile_data.current_basal;
        duration  = 30;
    }

    requestedTemp.duration = duration;
    requestedTemp.rate = Math.round((Math.round(rate / 0.05) * 0.05)*100)/100;
    requestedTemp.reason = reason;
    console.log(JSON.stringify(requestedTemp));
    return requestedTemp;
};

if (!module.parent) {
    var iob_input = process.argv.slice(2, 3).pop()
    var temps_input = process.argv.slice(3, 4).pop()
    var glucose_input = process.argv.slice(4, 5).pop()
    var profile_input = process.argv.slice(5, 6).pop()
    var offline_input = process.argv.slice(6, 7).pop()

    if (!iob_input || !temps_input || !glucose_input || !profile_input) {
        console.error('usage: ', process.argv.slice(0, 2), '<iob.json> <current-temps.json> <glucose.json> <profile.json> [Offline]');
        process.exit(1);
    }

    var cwd = process.cwd()
    var glucose_data = require(cwd + '/' + glucose_input);
    var temps_data = require(cwd + '/' + temps_input);
    var iob_data = require(cwd + '/' + iob_input);
    var profile_data = require(cwd + '/' + profile_input);

    if (typeof profile_data === 'undefined' || typeof profile_data.current_basal === 'undefined') {
        console.error('Error: could not get current basal rate');
        process.exit(1);
    }

    var max_iob = profile_data.max_iob; // maximum amount of non-bolus IOB OpenAPS will ever deliver

    // if target_bg is set, great. otherwise, if min and max are set, then set target to their average
    var target_bg;
    if (typeof profile_data.target_bg !== 'undefined') {
        target_bg = profile_data.target_bg;
    } else {
        if (typeof profile_data.max_bg !== 'undefined' && typeof profile_data.max_bg !== 'undefined') {
            target_bg = (profile_data.min_bg + profile_data.max_bg) / 2;
        } else {
            console.error('Error: could not determine target_bg');
            process.exit(1);
        }
    }

    var glucose_status = getLastGlucose(glucose_data);
    var bg = glucose_status.glucose;
    var tick;
    if (glucose_status.delta >= 0) { tick = "+" + glucose_status.delta; }
    else { tick = glucose_status.delta; }
    console.error("IOB: " + iob_data.iob.toFixed(2) + ", Bolus IOB: " + iob_data.bolusiob.toFixed(2));
    //calculate BG impact: the amount BG "should" be rising or falling based on insulin activity alone
    var bgi = -iob_data.activity * profile_data.sens * 5;
    console.error("Avg. Delta: " + glucose_status.avgdelta.toFixed(1) + ", BGI: " + bgi.toFixed(1));
    // project deviation over next 15 minutes
    var deviation = Math.round( 15 / 5 * ( glucose_status.avgdelta - bgi ) );
    console.error("15m deviation: " + deviation.toFixed(0));
    // calculate the naive (bolus calculator math) eventual BG based on net IOB and sensitivity
    var naive_eventualBG = Math.round( bg - (iob_data.iob * profile_data.sens) );
    // and adjust it for the deviation above
    var eventualBG = naive_eventualBG + deviation;
    // calculate what portion of that is due to bolusiob
    var bolusContrib = iob_data.bolusiob * profile_data.sens;
    // and add it back in to get snoozeBG, plus another 50% to avoid low-temping at mealtime
    var naive_snoozeBG = Math.round( naive_eventualBG + 1.5 * bolusContrib );
    // adjust that for deviation like we did eventualBG
    var snoozeBG = naive_snoozeBG + deviation;
    console.error("BG: " + bg + tick + " -> " + eventualBG + "-" + snoozeBG + " (Unadjusted: " + naive_eventualBG + "-" + naive_snoozeBG + ")");
    if (typeof eventualBG === 'undefined') { console.error('Error: could not calculate eventualBG'); }
    var requestedTemp = {
        'temp': 'absolute'
        , 'bg': bg
        , 'tick': tick
        , 'eventualBG': eventualBG
        , 'snoozeBG': snoozeBG
    };

    //if old reading from Dexcom do nothing

    var systemTime = new Date();
    var bgTime;
    if (glucose_data[0].display_time) {
        bgTime = new Date(glucose_data[0].display_time.replace('T', ' '));
    } else if (glucose_data[0].dateString) {
        bgTime = new Date(glucose_data[0].dateString);
    } else { console.error("Could not determine last BG time"); }
    var minAgo = (systemTime - bgTime) / 60 / 1000
    var threshold = profile_data.min_bg - 30;
    var reason="";

    if (minAgo < 10 && minAgo > -5) { // Dexcom data is recent, but not far in the future

        if (bg > 10) {  //Dexcom is in ??? mode or calibrating, do nothing. Asked @benwest for raw data in iter_glucose

            if (bg < threshold) { // low glucose suspend mode: BG is < ~80
                reason = "BG " + bg + "<" + threshold;
                console.error(reason);
                if (glucose_status.delta > 0) { // if BG is rising
                    if (temps_data.rate > profile_data.current_basal) { // if a high-temp is running
                        return setTempBasal(0, 0); // cancel high temp
                    } else if (temps_data.duration && eventualBG > profile_data.max_bg) { // if low-temped and predicted to go high from negative IOB
                        return setTempBasal(0, 0); // cancel low temp
                    } else {
                        reason = bg + "<" + threshold + "; no high-temp to cancel";
                        console.error(reason);
                    }
                }
                else { // BG is not yet rising
                    return setTempBasal(0, 30);
                }

            } else {

                // if BG is rising but eventual BG is below min, or BG is falling but eventual BG is above min
                if ((glucose_status.delta > 0 && eventualBG < profile_data.min_bg) || (glucose_status.delta < 0 && eventualBG >= profile_data.min_bg)) {
                    if (temps_data.duration > 0) { // if there is currently any temp basal running
                        // if it's a low-temp and eventualBG < profile_data.max_bg, let it run a bit longer
                        if (temps_data.rate <= profile_data.current_basal && eventualBG < profile_data.max_bg) {
                            reason = "BG" + tick + " but eventualBG " + eventualBG + "<" + profile_data.max_bg;
                            console.error(reason);
                        } else {
                            reason = tick + " and eventualBG " + eventualBG;
                            return setTempBasal(0, 0); // cancel temp
                        }
                    } else {
                        reason = tick + "; no temp to cancel";
                        console.error(reason);
                    }

                } else if (eventualBG < profile_data.min_bg) { // if eventual BG is below target:
                    // if this is just due to boluses, we can snooze until the bolus IOB decays (at double speed)
                    if (snoozeBG > profile_data.min_bg) { // if adding back in the bolus contribution BG would be above min
                        // if BG is falling and high-temped, or rising and low-temped, cancel
                        if (glucose_status.delta < 0 && temps_data.rate > profile_data.current_basal) {
                            reason = tick + " and temp " + temps_data.rate + " > basal " + profile_data.current_basal;
                            return setTempBasal(0, 0); // cancel temp
                        } else if (glucose_status.delta > 0 && temps_data.rate < profile_data.current_basal) {
                            reason = tick + " and temp " + temps_data.rate + " < basal " + profile_data.current_basal;
                            return setTempBasal(0, 0); // cancel temp
                        } else {
                            reason = "bolus snooze: eventual BG range " + eventualBG + "-" + snoozeBG;
                            console.error(reason);
                        }
                    } else {
                        // calculate 30m low-temp required to get projected BG up to target
                        // negative insulin required to get up to min:
                        //var insulinReq = Math.max(0, (target_bg - eventualBG) / profile_data.sens);
                        // use snoozeBG instead of eventualBG to more gradually ramp in any counteraction of the user's boluses
                        var insulinReq = Math.min(0, (snoozeBG - target_bg) / profile_data.sens);
                        // rate required to deliver insulinReq less insulin over 30m:
                        var rate = profile_data.current_basal + (2 * insulinReq);
                        rate = Math.round( rate * 1000 ) / 1000;
                        // if required temp < existing temp basal
                        if (typeof temps_data.rate !== 'undefined' && (temps_data.duration > 0 && rate > temps_data.rate - 0.1)) {
                            reason = "temp " + temps_data.rate + " <~ req " + rate + "U/hr";
                            console.error(reason);
                        } else {
                            reason = "Eventual BG " + eventualBG + "<" + profile_data.min_bg;
                            return setTempBasal(rate, 30);
                        }
                    }

                } else if (eventualBG > profile_data.max_bg) { // if eventual BG is above target:
                    // if iob is over max, just cancel any temps
                    var basal_iob = Math.round(( iob_data.iob - iob_data.bolusiob )*1000)/1000;
                    if (basal_iob > max_iob) {
                        reason = "basal_iob " + basal_iob + " > max_iob " + max_iob;
                        return setTempBasal(0, 0);
                    } else {
                        // calculate 30m high-temp required to get projected BG down to target
                        // additional insulin required to get down to max bg:
                        var insulinReq = (eventualBG - target_bg) / profile_data.sens;
                        // if that would put us over max_iob, then reduce accordingly
                        if (insulinReq > max_iob-basal_iob) {
                            reason = "max_iob " + max_iob + ", ";
                            insulinReq = max_iob-basal_iob;
                        }

                        // rate required to deliver insulinReq more insulin over 30m:
                        var rate = profile_data.current_basal + (2 * insulinReq);
                        rate = Math.round( rate * 1000 ) / 1000;

                        maxSafeBasal = Math.min(profile_data.max_basal, 3 * profile_data.max_daily_basal, 4 * profile_data.current_basal);
                        if (rate > maxSafeBasal) {
                            rate = maxSafeBasal;
                            //console.error(maxSafeBasal);
                        }
                        var insulinScheduled = temps_data.duration * (temps_data.rate - profile_data.current_basal) / 60;
                        if (insulinScheduled > insulinReq + 0.3) { // if current temp would deliver >0.3U more than the required insulin, lower the rate
                            reason = temps_data.duration + "@" + temps_data.rate + " > req " + insulinReq + "U";
                            return setTempBasal(rate, 30);
                        }
                        else if (typeof temps_data.rate == 'undefined' || temps_data.rate == 0) { // no temp is set
                            reason += "no temp, setting " + rate + "U/hr";
                            return setTempBasal(rate, 30);
                        }
                        else if (temps_data.duration > 0 && rate < temps_data.rate + 0.1) { // if required temp <~ existing temp basal
                            reason += "temp " + temps_data.rate + " >~ req " + rate + "U/hr";
                            console.error(reason);
                        } else { // required temp > existing temp basal
                            reason += "temp " + temps_data.rate + "<" + rate + "U/hr";
                            return setTempBasal(rate, 30);
                        }
                    }

                } else {
                    reason = eventualBG + " is in range. No temp required.";
                    if (temps_data.duration > 0) { // if there is currently any temp basal running
                        return setTempBasal(0, 0); // cancel temp
                    } else {
                        console.error(reason);
                    }
                }
            }

            if (offline_input == 'Offline') {
                // if no temp is running or required, set the current basal as a temp, so you can see on the pump that the loop is working
                if ((!temps_data.duration || (temps_data.rate == profile_data.current_basal)) && !requestedTemp.duration) {
                    reason = reason + "; setting current basal of " + profile_data.current_basal + " as temp";
                    return setTempBasal(profile_data.current_basal, 30);
                }
            }
        }  else {
            reason = "CGM is calibrating or in ??? state";
            console.error(reason);
        }
    } else {
        reason = "BG data is too old, or clock set incorrectly";
        console.error(reason);
    }

    requestedTemp.reason = reason;
    console.log(JSON.stringify(requestedTemp));
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * Copyright 2019 Google LLC. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const chalk = require('chalk');
const fetch = require('node-fetch');
const figures = require('figures');
const { readFileSync, writeFileSync } = require('fs');

let argv = null;
const apiUrl = 'https://api.github.com';

function checkpoint (message, success = true) {
  const prefix = success ? chalk.green(figures.tick) : chalk.red(figures.cross);
  console.info(`${prefix} ${message}`);
}

// grab files using GitHub API.
async function getContent (owner, repo, path) {
  const headers = {};
  if (argv.token) headers.authorization = `token ${argv.token}`;
  const res = await fetch(`${apiUrl}/repos/${owner}/${repo}/contents/${path}`, {
    headers: headers
  });
  if (res.status !== 200) {
    const err = Error(`unexpected status = ${res.status}`);
    err.status = res.status;
    throw err;
  }
  const content = (await res.json()).content;
  return JSON.parse(
    Buffer.from(content, 'base64').toString('utf8')
  );
}

// for each repo listed in sloth/repos.json pull down .repo-metadata.json.
async function collectRepoMetadata (repos) {
  const repoMetadata = {};
  for (let i = 0, repo; (repo = repos[i]) !== undefined; i++) {
    if (repo.language === 'nodejs') {
      try {
        const [o, r] = repo.repo.split('/');
        repoMetadata[r] = await getContent(o, r, '.repo-metadata.json');
        checkpoint(`${repo.repo} found .repo-metadata.json`);
      } catch (err) {
        if (err.status === 404) checkpoint(`${repo.repo} had no .repo-metadata.json`, false);
        else throw err;
      }
    }
  }
  return repoMetadata;
}

// Fills in README.mustache with contents loaded from sloth/repos.json.
// Given the simplicity of the template, we do not actually use a templating
// engine, instead calling string.replace.
function generateReadme (repoMetadata) {
  const template = readFileSync('./bin/README.mustache', 'utf8');
  const libraries = [];

  // filter libraries to only contain those with Google Cloud api_id,
  // standardizing naming along the way.
  Object.keys(repoMetadata).forEach(key => {
    const metadata = repoMetadata[key];
    if (metadata.api_id) {
      // making naming more consistent, sometimes we've appended Cloud,
      // sometimes Google Cloud.
      metadata.name_pretty = metadata.name_pretty.replace(/^(Google )?Cloud /, '');
      libraries.push(metadata);
    }
  });

  libraries.sort((a, b) => {
    return a.name_pretty.localeCompare(b.name_pretty);
  });

  let partial = '';
  libraries.forEach((lib) => {
    partial += `| [${lib.name_pretty}](https://github.com/${lib.repo}) | [:notebook:](${lib.client_documentation}) | \`npm i ${lib.distribution_name}\` | [enable](https://console.cloud.google.com/flows/enableapi?apiid=${lib.api_id}) | ${lib.requires_billing ? figures.cross : figures.tick} |\n`;
  });

  writeFileSync('./README.md', template.replace('{{libraries}}', partial), 'utf8');
}

require('yargs')
  .command('$0', 'generate README from sloth list of repos', () => {}, async (_argv) => {
    argv = _argv;
    const repos = (await getContent('googleapis', 'sloth', 'repos.json')).repos;
    checkpoint('loaded list of repos from sloth');
    const repoMetadata = await collectRepoMetadata(repos);
    generateReadme(repoMetadata);
  })
  .option('token', {
    describe: 'GitHub authorization token'
  })
  .parse();
<commit_msg>chore: update license headers<commit_after>#!/usr/bin/env node
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const chalk = require('chalk');
const fetch = require('node-fetch');
const figures = require('figures');
const { readFileSync, writeFileSync } = require('fs');

let argv = null;
const apiUrl = 'https://api.github.com';

function checkpoint (message, success = true) {
  const prefix = success ? chalk.green(figures.tick) : chalk.red(figures.cross);
  console.info(`${prefix} ${message}`);
}

// grab files using GitHub API.
async function getContent (owner, repo, path) {
  const headers = {};
  if (argv.token) headers.authorization = `token ${argv.token}`;
  const res = await fetch(`${apiUrl}/repos/${owner}/${repo}/contents/${path}`, {
    headers: headers
  });
  if (res.status !== 200) {
    const err = Error(`unexpected status = ${res.status}`);
    err.status = res.status;
    throw err;
  }
  const content = (await res.json()).content;
  return JSON.parse(
    Buffer.from(content, 'base64').toString('utf8')
  );
}

// for each repo listed in sloth/repos.json pull down .repo-metadata.json.
async function collectRepoMetadata (repos) {
  const repoMetadata = {};
  for (let i = 0, repo; (repo = repos[i]) !== undefined; i++) {
    if (repo.language === 'nodejs') {
      try {
        const [o, r] = repo.repo.split('/');
        repoMetadata[r] = await getContent(o, r, '.repo-metadata.json');
        checkpoint(`${repo.repo} found .repo-metadata.json`);
      } catch (err) {
        if (err.status === 404) checkpoint(`${repo.repo} had no .repo-metadata.json`, false);
        else throw err;
      }
    }
  }
  return repoMetadata;
}

// Fills in README.mustache with contents loaded from sloth/repos.json.
// Given the simplicity of the template, we do not actually use a templating
// engine, instead calling string.replace.
function generateReadme (repoMetadata) {
  const template = readFileSync('./bin/README.mustache', 'utf8');
  const libraries = [];

  // filter libraries to only contain those with Google Cloud api_id,
  // standardizing naming along the way.
  Object.keys(repoMetadata).forEach(key => {
    const metadata = repoMetadata[key];
    if (metadata.api_id) {
      // making naming more consistent, sometimes we've appended Cloud,
      // sometimes Google Cloud.
      metadata.name_pretty = metadata.name_pretty.replace(/^(Google )?Cloud /, '');
      libraries.push(metadata);
    }
  });

  libraries.sort((a, b) => {
    return a.name_pretty.localeCompare(b.name_pretty);
  });

  let partial = '';
  libraries.forEach((lib) => {
    partial += `| [${lib.name_pretty}](https://github.com/${lib.repo}) | [:notebook:](${lib.client_documentation}) | \`npm i ${lib.distribution_name}\` | [enable](https://console.cloud.google.com/flows/enableapi?apiid=${lib.api_id}) | ${lib.requires_billing ? figures.cross : figures.tick} |\n`;
  });

  writeFileSync('./README.md', template.replace('{{libraries}}', partial), 'utf8');
}

require('yargs')
  .command('$0', 'generate README from sloth list of repos', () => {}, async (_argv) => {
    argv = _argv;
    const repos = (await getContent('googleapis', 'sloth', 'repos.json')).repos;
    checkpoint('loaded list of repos from sloth');
    const repoMetadata = await collectRepoMetadata(repos);
    generateReadme(repoMetadata);
  })
  .option('token', {
    describe: 'GitHub authorization token'
  })
  .parse();
<|endoftext|>


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

exports.command = {
  description: 'fill your projects.db from GitHub'
};

if (require.main !== module) {
  return;
}

var async = require('async');
var moment = require('moment');
var program = require('commander');
var request = require('request');
var _ = require('lodash');

var config = require('../lib/config.js');
var paths = require('../lib/paths.js');
var storage = require('../lib/storage.js');

var ATTRIBUTES = [
  'name',
  'description',
  'homepage',
  'language',
  'created_at',
  'updated_at',
  'pushed_at',
  'fork',
  'private',
  'html_url',
  'git_url',
  'ssh_url',
  'clone_url'
];

var GITHUB_URL_MAPPINGS = {
  git: 'git_url',
  https: 'clone_url',
  ssh: 'ssh_url'
};

var SIX_MONTHS_AGO = moment().subtract('months', 6);

var GITHUB_BASE_URL = 'https://api.github.com';

program.option('--url-type [type]', 'The Git URL type to use ' +
  '[git, ssh, https]', 'https');

program.option('-u, --username', 'The GitHub username');

program._name = 'github';
program.parse(process.argv);

if ((!program.username && !config.github.username) &&
  !config.github.access_token) {
  console.error('Please specify a GitHub username or an access_token in',
    paths.CONFIG_FILE, 'or a username via the -u, --username flag.');

  process.exit(1);
}

var username = program.username || config.github.username;

var getRepositories = exports.getRepositories = function (cb) {
  var count;
  var page = 0;

  var allRepositories = [];

  async.until(function () {
    return count === 0;
  },
  function (cbUntil) {
    page++;

    console.log('Retrieving repositories page', page);

    var qs = {
      page: page
    };

    var url = GITHUB_BASE_URL;

    if (config.github.access_token) {
      url += '/user/repos';

      qs.access_token = config.github.access_token;
    } else {
      url += '/users/' + username + '/repos';
    }

    request.get({
      url: url,
      qs: qs,
      json: true
    }, function (err, resp, repositories) {
      repositories = _.map(repositories, function (repo) {
        return _.pick(repo, ATTRIBUTES);
      });

      allRepositories.push.apply(allRepositories, repositories);

      count = repositories.length;

      cbUntil(err);
    });
  },
  function (err) {
    cb(err, allRepositories);
  });
};

function isActive(repository) {
  var updated = moment(repository.updated_at);
  var pushed = moment(repository.pushed_at);

  return (updated && updated.isAfter(SIX_MONTHS_AGO)) ||
    (pushed && pushed.isAfter(SIX_MONTHS_AGO));
}

var fillProjects = exports.fillProjects = function (cb) {
  getRepositories(function (err, repositories) {
    var projects = [];

    repositories.forEach(function (repository) {
      var project = {
        name: repository.name,
        repository: repository[GITHUB_URL_MAPPINGS[program.urlType]],
        homepage: repository.homepage || repository.html_url,
        language: repository.language,
        role: repository.fork ? 'contributor' : 'creator',
        released: !repository.private,
        status: isActive(repository) ? 'active' : 'inactive'
      };

      projects.push(project);
    });

    cb(err, projects);
  });
};

storage.setup(function () {
  console.log('Filling projects from GitHub');

  fillProjects(function (err, projects) {
    if (err) {
      console.log('There was an error accessing your GitHub data:', err);

      process.exit(1);
    }

    async.forEachSeries(projects, function (project, cbForEach) {
      console.log('Adding', project.name);

      storage.upsertProject(project.name, project, cbForEach);
    });
  });
});
<commit_msg>Add in forgotten description attribute<commit_after>#!/usr/bin/env node

exports.command = {
  description: 'fill your projects.db from GitHub'
};

if (require.main !== module) {
  return;
}

var async = require('async');
var moment = require('moment');
var program = require('commander');
var request = require('request');
var _ = require('lodash');

var config = require('../lib/config.js');
var paths = require('../lib/paths.js');
var storage = require('../lib/storage.js');

var ATTRIBUTES = [
  'name',
  'description',
  'homepage',
  'language',
  'created_at',
  'updated_at',
  'pushed_at',
  'fork',
  'private',
  'html_url',
  'git_url',
  'ssh_url',
  'clone_url'
];

var GITHUB_URL_MAPPINGS = {
  git: 'git_url',
  https: 'clone_url',
  ssh: 'ssh_url'
};

var SIX_MONTHS_AGO = moment().subtract('months', 6);

var GITHUB_BASE_URL = 'https://api.github.com';

program.option('--url-type [type]', 'The Git URL type to use ' +
  '[git, ssh, https]', 'https');

program.option('-u, --username', 'The GitHub username');

program._name = 'github';
program.parse(process.argv);

if ((!program.username && !config.github.username) &&
  !config.github.access_token) {
  console.error('Please specify a GitHub username or an access_token in',
    paths.CONFIG_FILE, 'or a username via the -u, --username flag.');

  process.exit(1);
}

var username = program.username || config.github.username;

var getRepositories = exports.getRepositories = function (cb) {
  var count;
  var page = 0;

  var allRepositories = [];

  async.until(function () {
    return count === 0;
  },
  function (cbUntil) {
    page++;

    console.log('Retrieving repositories page', page);

    var qs = {
      page: page
    };

    var url = GITHUB_BASE_URL;

    if (config.github.access_token) {
      url += '/user/repos';

      qs.access_token = config.github.access_token;
    } else {
      url += '/users/' + username + '/repos';
    }

    request.get({
      url: url,
      qs: qs,
      json: true
    }, function (err, resp, repositories) {
      repositories = _.map(repositories, function (repo) {
        return _.pick(repo, ATTRIBUTES);
      });

      allRepositories.push.apply(allRepositories, repositories);

      count = repositories.length;

      cbUntil(err);
    });
  },
  function (err) {
    cb(err, allRepositories);
  });
};

function isActive(repository) {
  var updated = moment(repository.updated_at);
  var pushed = moment(repository.pushed_at);

  return (updated && updated.isAfter(SIX_MONTHS_AGO)) ||
    (pushed && pushed.isAfter(SIX_MONTHS_AGO));
}

var fillProjects = exports.fillProjects = function (cb) {
  getRepositories(function (err, repositories) {
    var projects = [];

    repositories.forEach(function (repository) {
      var project = {
        name: repository.name,
        description: repository.description,
        repository: repository[GITHUB_URL_MAPPINGS[program.urlType]],
        homepage: repository.homepage || repository.html_url,
        language: repository.language,
        role: repository.fork ? 'contributor' : 'creator',
        released: !repository.private,
        status: isActive(repository) ? 'active' : 'inactive'
      };

      projects.push(project);
    });

    cb(err, projects);
  });
};

storage.setup(function () {
  console.log('Filling projects from GitHub');

  fillProjects(function (err, projects) {
    if (err) {
      console.log('There was an error accessing your GitHub data:', err);

      process.exit(1);
    }

    async.forEachSeries(projects, function (project, cbForEach) {
      console.log('Adding', project.name);

      storage.upsertProject(project.name, project, cbForEach);
    });
  });
});
<|endoftext|>


<commit_before>(function() {
	var Collection = function WCollection(entities, type) {
		this._type = undefined;
		this._data = [];

		if (entities instanceof Array) {
			if (!type) {
				type = undefined;
			}

			for (var i = 0; i < entities.length; i++) {
				var entity = entities[i];

				var result = this.add(entity);

				if (result === false) {
					continue;
				}

				if (entity.constructor) {
					if (typeof type == 'undefined') {
						type = entity.constructor;
					} else if (type !== null && type !== entity.constructor) {
						type = null;
					}
				}
			}
		}

		this.type(type);
	};
	Collection.prototype = {
		type: function $_WCollection_type(type) {
			if (typeof type == 'undefined') {
				return this._type;
			} else {
				if (!type) {
					return false;
				}

				var that = this;

				this._type = type;

				this._methods = [];
				for (var attr in type.prototype) {
					if (!this[attr] && typeof type.prototype[attr] == 'function') {
						this[attr] = (function() {
							return (function() {
								var args = arguments;
								that.each(function() {
									this[attr].apply(this, args);
								});
							});
						})();
					}
				}
			}
		},
		add: function $_WCollection_add(entity) {
			if (this.type() && !Webos.isInstanceOf(entity, this.type())) {
				return false;
			}

			this._data.push(entity);
		},
		remove: function $_WCollection_remove(i) {
			this._data = this._data.slice(0,i).concat(this._data.slice(i+1));
		},
		each: function $_WCollection_each(fn) {
			if (typeof fn != 'function') {
				return false;
			}

			for (var i = 0; i < this._data.length; i++) {
				var result = fn.call(this._data[i]);
				if (result === false) {
					break;
				}
			}
		},
		list: function $_WCollection_list() {
			return this._data;
		},
		item: function $_WCollection_item(i) {
			return this._data[i];
		},
		length: function $_WCollection_length() {
			return this._data.length;
		}
	};

	Webos.Collection = Collection;
})();<commit_msg>Added comments to Webos.Collection.<commit_after>(function() {
	/**
	 * A collection of objects.
	 * @param {Array} [entities] Entities contained in the collection.
	 * @param {Function} [type] This collection's type (the entities' class).
	 * @constructor
	 */
	var Collection = function WCollection(entities, type) {
		this._type = undefined;
		this._data = [];

		if (entities instanceof Array) {
			if (!type) {
				type = undefined;
			}

			for (var i = 0; i < entities.length; i++) {
				var entity = entities[i];

				var result = this.add(entity);

				if (result === false) {
					continue;
				}

				if (entity.constructor) {
					if (typeof type == 'undefined') {
						type = entity.constructor;
					} else if (type !== null && type !== entity.constructor) {
						type = null;
					}
				}
			}
		}

		this.type(type);
	};
	Collection.prototype = {
		/**
		 * Get/set this collection's type.
		 * The collection's type is the parent class of each entity.
		 * @param {Function} [type] If specified, the type of the collection will be set.
		 * @returns {Function|undefined} If no type is specified, the collection's type will be returned.
		 */
		type: function $_WCollection_type(type) {
			if (typeof type == 'undefined') {
				return this._type;
			} else {
				if (!type) {
					return false;
				}

				var that = this;

				this._type = type;

				this._methods = [];
				for (var attr in type.prototype) {
					if (!this[attr] && typeof type.prototype[attr] == 'function') {
						this[attr] = (function() {
							return (function() {
								var args = arguments;
								that.each(function() {
									this[attr].apply(this, args);
								});
							});
						})();
					}
				}
			}
		},
		/**
		 * Add an entity to the collection.
		 * @param entity The entity to add.
		 */
		add: function $_WCollection_add(entity) {
			if (this.type() && !Webos.isInstanceOf(entity, this.type())) {
				return false;
			}

			this._data.push(entity);
		},
		/**
		 * Remove an entity in the collection.
		 * @param {Number} i The index of the entity in the collection.
		 */
		remove: function $_WCollection_remove(i) {
			this._data = this._data.slice(0,i).concat(this._data.slice(i+1));
		},
		/**
		 * Execute a callback on each entity in the collection.
		 * The function will be executed in the context of each entity, one by one. If the callback returns false, no more entities will be processed.
		 * @param {Function} fn The callback.
		 */
		each: function $_WCollection_each(fn) {
			if (typeof fn != 'function') {
				return false;
			}

			for (var i = 0; i < this._data.length; i++) {
				var result = fn.call(this._data[i]);
				if (result === false) {
					break;
				}
			}
		},
		/**
		 * Get a list of entities contained in the collection.
		 * @returns {Array} An array containing all entities.
		 */
		list: function $_WCollection_list() {
			return this._data;
		},
		/**
		 * Get a specified entity in the collection.
		 * @param {Number} i The index of the entity in the collection.
		 * @returns The corresponding entity.
		 */
		item: function $_WCollection_item(i) {
			return this._data[i];
		},
		/**
		 * Get the number of entities contained in the collection.
		 * @returns {Number} The number of entities.
		 */
		length: function $_WCollection_length() {
			return this._data.length;
		}
	};

	Webos.Collection = Collection;
})();
<|endoftext|>


<commit_before>"use strict";
var path = require("path");
var _ = require("lodash");

var env = process.env.NODE_ENV = process.env.NODE_ENV || "development";

var base = {
  app: {
    root: path.normalize(path.join(__dirname, "/..")),
    env: env,
  },
};

var specific = {
  development: {
    app: {
      port: 3000,
      name: "Koa React Gulp Mongoose Mocha - Dev",
      keys: [ "super-secret-hurr-durr" ],
    },
    mongo: {
      url: "mongodb://localhost/koareactfullexample_dev",
    },
  },
  test: {
    app: {
      port: 3001,
      name: "Koa React Gulp Mongoose Mocha - Test realm",
      keys: [ "super-secret-hurr-durr" ],
    },
    mongo: {
      url: "mongodb://localhost/koareactfullexample_test",
    },
  },
  production: {
    app: {
      port: process.env.PORT || 3000,
      name: "Koa React Gulp Mongoose Mocha",
    },
    mongo: {
      url: "mongodb://localhost/koareactfullexample",
    },
  },
};

module.exports = _.merge(base, specific[env]);
<commit_msg>DB config loaded.<commit_after>"use strict";

var path = require("path");
var _ = require("lodash");
var db = require('../database.json');

var env = process.env.NODE_ENV = process.env.NODE_ENV || "development";

var base = {
  app: {
    root: path.normalize(path.join(__dirname, "/..")),
    env: env,
  },
};

var specific = {
  development: {
    app: {
      port: 3000,
      name: "Koa React Gulp Mongoose Mocha - Dev",
      keys: [ "super-secret-hurr-durr" ],
    },
    database: db.dev,
    mongo: {
      url: "mongodb://localhost/koareactfullexample_dev",
    },
  },
  test: {
    app: {
      port: 3001,
      name: "Koa React Gulp Mongoose Mocha - Test realm",
      keys: [ "super-secret-hurr-durr" ],
    },
    database: db.test,
    mongo: {
      url: "mongodb://localhost/koareactfullexample_test",
    },
  },
  production: {
    app: {
      port: process.env.PORT || 3000,
      name: "Koa React Gulp Mongoose Mocha",
    },
    database: db.prod,
    mongo: {
      url: "mongodb://localhost/koareactfullexample",
    },
  },
};

module.exports = _.merge(base, specific[env]);
<|endoftext|>


<commit_before>/**
 * Copyright 2015-2016, Google, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

// Hierarchical node.js configuration with command-line arguments, environment
// variables, and files.
const nconf = module.exports = require('nconf');
const path = require('path');

nconf
  // 1. Command-line arguments
  .argv()
  // 2. Environment variables
  .env([
    'CLOUD_BUCKET',
    'DATA_BACKEND',
    'GCLOUD_PROJECT',
    'PORT',
    'CLIENT_ID',
    'CLIENT_SECRET'
  ])
  // 3. Config file
  .file({file: path.join(__dirname, 'config.json')})
  // 4. Defaults
  .defaults({
    // Typically you will create a bucket with the same name as your project ID.
    CLOUD_BUCKET: '',
    DATA_BACKEND: 'datastore',

    // This is the id of your project in the Google Cloud Developers Console.
    GCLOUD_PROJECT: '',

    // Port the HTTP server
    PORT: 8080
  });

// Check for required settings
checkConfig('GCLOUD_PROJECT');
checkConfig('CLOUD_BUCKET');
checkConfig('CLIENT_ID');
checkConfig('CLIENT_SECRET');

function checkConfig(setting) {
  if (!nconf.get(setting)) {
    throw new Error('You must set the ' + setting + ' environment variable or' +
      ' add it to config.json!');
  }
}
<commit_msg>Look for LIGHTHOUSE_SERVER in env variable (#164)<commit_after>/**
 * Copyright 2015-2016, Google, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

// Hierarchical node.js configuration with command-line arguments, environment
// variables, and files.
const nconf = module.exports = require('nconf');
const path = require('path');

nconf
  // 1. Command-line arguments
  .argv()
  // 2. Environment variables
  .env([
    'CLOUD_BUCKET',
    'DATA_BACKEND',
    'GCLOUD_PROJECT',
    'PORT',
    'CLIENT_ID',
    'CLIENT_SECRET',
    'LIGHTHOUSE_SERVER'
  ])
  // 3. Config file
  .file({file: path.join(__dirname, 'config.json')})
  // 4. Defaults
  .defaults({
    // Typically you will create a bucket with the same name as your project ID.
    CLOUD_BUCKET: '',
    DATA_BACKEND: 'datastore',

    // This is the id of your project in the Google Cloud Developers Console.
    GCLOUD_PROJECT: '',

    // Port the HTTP server
    PORT: 8080
  });

// Check for required settings
checkConfig('GCLOUD_PROJECT');
checkConfig('CLOUD_BUCKET');
checkConfig('CLIENT_ID');
checkConfig('CLIENT_SECRET');

function checkConfig(setting) {
  if (!nconf.get(setting)) {
    throw new Error('You must set the ' + setting + ' environment variable or' +
      ' add it to config.json!');
  }
}
<|endoftext|>


<commit_before>/* Magic Mirror Config Sample
 *
 * By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 */

var config = {
	port: 8080,
	ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],

	language: 'ru',
	timeFormat: 24,
	units: 'metric',

	modules: [
		{
			module: 'alert',
		},
		{
			module: 'clock',
			position: 'top_left'
		},
		{
			module: 'calendar',
			header: 'События',
			position: 'top_left',
            maximumEntries: 20,
			config: {
				calendars: [
					{
						symbol: 'calendar-check-o ',
                        repeatingCountTitle: "Дни рождения",
						url: 'https://calendar.google.com/calendar/ical/4h5ajk6irlvakqm3b1le9j7g78%40group.calendar.google.com/private-ecbc42870296bffac13a063ddf51d5be/basic.ics'
					},
					{
						symbol: 'home ',
                        repeatingCountTitle: "Государственные праздники",
						url: 'https://calendar.google.com/calendar/ical/ru.ukrainian%23holiday%40group.v.calendar.google.com/public/basic.ics'
					}
				]
			}
		},
		{
			module: 'compliments',
			position: 'lower_third',
            disabled: true
		},
		{
			module: 'currentweather',
			position: 'top_right',
			config: {
				location: 'Одесса',
				locationID: '698740',  //ID from http://www.openweathermap.org
				appid: '07ecdcb2d4d25a1e1a3309c9ab276b62'
			}
		},
		{
			module: 'weatherforecast',
			position: 'top_right',
			header: 'Прогноз погоды',
            showRainAmount: true,
            maxNumberOfDays: 10,
			config: {
				location: 'Одесса',
				locationID: '698740',  //ID from http://www.openweathermap.org
				appid: '984d547837c83f16e3499e3f8bb944a7'
			}
		},
		{
			module: 'newsfeed',
			position: 'bottom_bar',
			config: {
				feeds: [
					{
						title: "Афиша www.048.ua",
						url: "http://www.048.ua/rss/afisha"
					},
                    /*
					{
						title: "Афиша Одесса",
						url: "http://md-eksperiment.org/rss.php"
					}
                    */
				],
				showSourceTitle: true,
				showPublishDate: true,
                showDescription: true,
                updateInterval: 20000
			}
		},
        {
          module: 'iFrame',
          position: 'middle_center', // This can be any of the regions.
          config: {
            url: "https://calendar.google.com/calendar/embed?showTitle=0&showNav=0&showDate=0&showPrint=0&showTabs=0&showCalendars=0&height=600&wkst=2&hl=ru&bgcolor=%23333333&src=ht3jlfaac5lfd6263ulfh4tql8%40group.calendar.google.com&color=%238C500B&src=4h5ajk6irlvakqm3b1le9j7g78%40group.calendar.google.com&color=%23B1365F&src=ru.ukrainian%23holiday%40group.v.calendar.google.com&color=%230F4B38&ctz=Europe%2FKiev",
            width: "800px", // Optional. Default: 100%
            height: "600px", //Optional. Default: 100px
          }
        },
        {
          module: "updatenotification",
          position: "top_bar"
        },
    ]

};

/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== 'undefined') {module.exports = config;}
<commit_msg>Disable iframe module. Add photo module<commit_after>/* Magic Mirror Config Sample
 *
 * By Michael Teeuw http://michaelteeuw.nl
 * MIT Licensed.
 */

var config = {
	port: 8080,
	ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:172.24.0.1"],

	language: 'ru',
	timeFormat: 24,
	units: 'metric',

	modules: [
		{
			module: 'alert',
		},
		{
			module: 'clock',
			position: 'top_left'
		},
		{
			module: 'calendar',
			header: 'События',
			position: 'top_left',
            maximumEntries: 20,
			config: {
				calendars: [
					{
						symbol: 'calendar-check-o ',
                        repeatingCountTitle: "Дни рождения",
						url: 'https://calendar.google.com/calendar/ical/4h5ajk6irlvakqm3b1le9j7g78%40group.calendar.google.com/private-ecbc42870296bffac13a063ddf51d5be/basic.ics'
					},
					{
						symbol: 'home ',
                        repeatingCountTitle: "Государственные праздники",
						url: 'https://calendar.google.com/calendar/ical/ru.ukrainian%23holiday%40group.v.calendar.google.com/public/basic.ics'
					}
				]
			}
		},
		{
			module: 'compliments',
			position: 'lower_third',
            disabled: true
		},
		{
			module: 'currentweather',
			position: 'top_right',
			config: {
				location: 'Одесса',
				locationID: '698740',  //ID from http://www.openweathermap.org
				appid: '07ecdcb2d4d25a1e1a3309c9ab276b62'
			}
		},
		{
			module: 'weatherforecast',
			position: 'top_right',
			header: 'Прогноз погоды',
            showRainAmount: true,
            maxNumberOfDays: 10,
			config: {
				location: 'Одесса',
				locationID: '698740',  //ID from http://www.openweathermap.org
				appid: '984d547837c83f16e3499e3f8bb944a7'
			}
		},
		{
			module: 'newsfeed',
			position: 'bottom_bar',
			config: {
				feeds: [
					{
						title: "Афиша www.048.ua",
						url: "http://www.048.ua/rss/afisha"
					},
                    /*
					{
						title: "Афиша Одесса",
						url: "http://md-eksperiment.org/rss.php"
					}
                    */
				],
				showSourceTitle: true,
				showPublishDate: true,
                showDescription: true,
                updateInterval: 20000
			}
		},
        {
          module: 'iFrame',
          position: 'middle_center', // This can be any of the regions.
          disabled: true,
          config: {
            url: "https://calendar.google.com/calendar/embed?...",
            width: "500px", // Optional. Default: 100%
            height: "550px", //Optional. Default: 100px
          }
        },
        {
          module: 'MMM-RandomPhoto',
          position: 'fullscreen_below',
          config: {
            opacity: 0.3,
            animationSpeed: 500,
            updateInterval: 60,
            url: 'https://unsplash.it/1920/1080/?random'
          }
        },
        {
          module: "updatenotification",
          position: "top_bar"
        },
    ]

};

/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== 'undefined') {module.exports = config;}
<|endoftext|>


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

let chalk = require('chalk');
let _ = require('lodash');
let { build, config } = require('./env.config');
let git = require('simple-git')();

let {TRAVIS, TRAVIS_BRANCH, TRAVIS_PULL_REQUEST, AZURE_WA_USERNAME, AZURE_WA_SITE, AZURE_WA_PASSWORD } = process.env;

/* Check if the code is running inside of travis.ci. If not abort immediately. */
if (!TRAVIS) {
    exit('Not running inside of Travis. Skipping deploy', true);
}

if (!_.isString(AZURE_WA_USERNAME)) {
    exit('"AZURE_WA_USERNAME" is a required global variable', true);
}

if (!_.isString(AZURE_WA_PASSWORD)) {
    exit('"AZURE_WA_PASSWORD" is a required global variable', true);
}

if (!_.isString(AZURE_WA_SITE)) {
    exit('"AZURE_WA_SITE" is a required global variable', true);
}

/* Check if the branch name is valid. */
let slot = _.isString(TRAVIS_BRANCH) && _.kebabCase(TRAVIS_BRANCH);
if (!slot) {
    exit('Invalid branch name. Skipping deploy', true);
}

switch (slot) {
    case 'master':
    case 'dev':
    case 'edge':
    case 'build':
        slot = 'edge';
        break;
}

/* Check if there is a configuration defined inside of config/env.config.js. */
let buildConfig = config[slot];
if (buildConfig == null || slot === 'local') {
    exit('No deployment configuration found for ' + slot + '. Skipping deploy');
}

/* If 'production' then apply the pull request only constraint. */
if (slot === 'production') {
    if (!TRAVIS_PULL_REQUEST) {
        exit('Deployments to "production" can only be done via pull requests.');
    }
    else {
        slot = 'staging';
    }
}

let url = 'https://'
    + AZURE_WA_USERNAME + ':'
    + AZURE_WA_PASSWORD + '@'
    + AZURE_WA_SITE + '-'
    + slot + '.scm.azurewebsites.net:443/'
    + AZURE_WA_SITE + '.git';

log('Deploying to ' + AZURE_WA_SITE + '-' + slot);

try {
    git.addConfig('user.name', 'Travis CI')
        .addConfig('user.email', AZURE_WA_USERNAME + 'microsoft.com')
        .checkout('HEAD')
        .add(['.', '-A', '-f'])
        .reset(['--', 'node_modules/**'])
        .status()
        .commit('Deployment commit')
        .then(() => log('Pushing to https://' + AZURE_WA_SITE + '-' + slot + '.azurewebsites.net'))
        .push(['-f', '-q', url, 'HEAD:refs/heads/master'], (err) => {
            if (err) {
                return exit(err, true);
            }
        })
        .then(() => {
            console.log(chalk.bold.green('Successfully deployed to https://' + AZURE_WA_SITE + '-' + slot + '.azurewebsites.net'))
            process.exit(0);
        });
}
catch (error) {
    exit(error, true);
}

function log(message) {
    console.log(chalk.bold.cyan(message));
}

function exit(reason, abort) {
    if (_.isString(reason)) {
        reason += '. Skipping deployment.'
    }

    if (reason) {
        abort ? console.log(chalk.bold.red(reason)) : console.log(chalk.bold.yellow(reason));
    }

    return abort ? process.exit(1) : process.exit(0);
}<commit_msg>removing sensitive info from logs<commit_after>#!/usr/bin/env node --harmony

let chalk = require('chalk');
let _ = require('lodash');
let { build, config } = require('./env.config');
let git = require('simple-git')();

let {TRAVIS, TRAVIS_BRANCH, TRAVIS_PULL_REQUEST, AZURE_WA_USERNAME, AZURE_WA_SITE, AZURE_WA_PASSWORD } = process.env;

/* Check if the code is running inside of travis.ci. If not abort immediately. */
if (!TRAVIS) {
    exit('Not running inside of Travis. Skipping deploy', true);
}

if (!_.isString(AZURE_WA_USERNAME)) {
    exit('"AZURE_WA_USERNAME" is a required global variable', true);
}

if (!_.isString(AZURE_WA_PASSWORD)) {
    exit('"AZURE_WA_PASSWORD" is a required global variable', true);
}

if (!_.isString(AZURE_WA_SITE)) {
    exit('"AZURE_WA_SITE" is a required global variable', true);
}

/* Check if the branch name is valid. */
let slot = _.isString(TRAVIS_BRANCH) && _.kebabCase(TRAVIS_BRANCH);
if (!slot) {
    exit('Invalid branch name. Skipping deploy', true);
}

switch (slot) {
    case 'master':
    case 'dev':
    case 'edge':
    case 'build':
        slot = 'edge';
        break;
}

/* Check if there is a configuration defined inside of config/env.config.js. */
let buildConfig = config[slot];
if (buildConfig == null || slot === 'local') {
    exit('No deployment configuration found for ' + slot + '. Skipping deploy');
}

/* If 'production' then apply the pull request only constraint. */
if (slot === 'production') {
    if (!TRAVIS_PULL_REQUEST) {
        exit('Deployments to "production" can only be done via pull requests.');
    }
    else {
        slot = 'staging';
    }
}

let url = 'https://'
    + AZURE_WA_USERNAME + ':'
    + AZURE_WA_PASSWORD + '@'
    + AZURE_WA_SITE + '-'
    + slot + '.scm.azurewebsites.net:443/'
    + AZURE_WA_SITE + '.git';

log('Deploying to ' + AZURE_WA_SITE + '-' + slot);

try {
    git.addConfig('user.name', 'Travis CI')
        .addConfig('user.email', AZURE_WA_USERNAME + 'microsoft.com')
        .checkout('HEAD')
        .add(['.', '-A', '-f'])
        .reset(['--', 'node_modules/**'])
        .status()
        .commit('Deployment commit')
        .then(() => log('Pushing to https://' + AZURE_WA_SITE + '-' + slot + '.azurewebsites.net'))
        .push(['-f', '-q', url, 'HEAD:refs/heads/master'], (err) => {
            if (err) {
                return exit('Deployment failed. Please fix the build and try again.', true);
            }
        })
        .then(() => {
            console.log(chalk.bold.green('Successfully deployed to https://' + AZURE_WA_SITE + '-' + slot + '.azurewebsites.net'))
            process.exit(0);
        });
}
catch (error) {
    exit(error, true);
}

function log(message) {
    console.log(chalk.bold.cyan(message));
}

function exit(reason, abort) {
    if (_.isString(reason)) {
        reason += '. Skipping deployment.'
    }

    if (reason) {
        abort ? console.log(chalk.bold.red(reason)) : console.log(chalk.bold.yellow(reason));
    }

    return abort ? process.exit(1) : process.exit(0);
}<|endoftext|>


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

let chalk = require('chalk');
let _ = require('lodash');
let { build, config } = require('./env.config');
let git = require('simple-git')();

let {TRAVIS, TRAVIS_BRANCH, TRAVIS_PULL_REQUEST, TRAVIS_COMMIT_MESSAGE, AZURE_WA_USERNAME, AZURE_WA_SITE, AZURE_WA_PASSWORD } = process.env;

log('Deploying commit: ' + TRAVIS_COMMIT_MESSAGE + ' by Travis');

/* Check if the code is running inside of travis.ci. If not abort immediately. */
if (!TRAVIS) {
    exit('Not running inside of Travis. Skipping deploy', true);
}

if (!_.isString(AZURE_WA_USERNAME)) {
    exit('"AZURE_WA_USERNAME" is a required global variable', true);
}

if (!_.isString(AZURE_WA_PASSWORD)) {
    exit('"AZURE_WA_PASSWORD" is a required global variable', true);
}

if (!_.isString(AZURE_WA_SITE)) {
    exit('"AZURE_WA_SITE" is a required global variable', true);
}

/* Check if the branch name is valid. */
let slot = _.isString(TRAVIS_BRANCH) && _.kebabCase(TRAVIS_BRANCH);
if (!slot) {
    exit('Invalid branch name. Skipping deploy', true);
}

switch (slot) {
    case 'master':
        slot = 'edge';
        break;
}

/* Check if there is a configuration defined inside of config/env.config.js. */
let buildConfig = config[slot];
if (buildConfig == null || slot === 'local') {
    exit('No deployment configuration found for ' + slot + '. Skipping deployment.');
}

/* If 'production' then apply the pull request only constraint. */
if (slot === 'production') {
    log('Production Deployment - Pull Request Status: ' + TRAVIS_PULL_REQUEST);
    if (TRAVIS_PULL_REQUEST == false) {
        exit('Deployments to "production" can only be done via pull requests.');
    }
    else {
        slot = 'staging';
    }
}

let url = 'https://'
    + AZURE_WA_USERNAME + ':'
    + AZURE_WA_PASSWORD + '@'
    + AZURE_WA_SITE + '-'
    + slot + '.scm.azurewebsites.net:443/'
    + AZURE_WA_SITE + '.git';

log('Deploying to ' + AZURE_WA_SITE + '-' + slot);

try {
    git.outputHandler((command, stdout) => null)
        .addConfig('user.name', 'Travis CI')
        .addConfig('user.email', 'travis.ci@microsoft.com')
        .checkout('HEAD')
        .add(['.', '-A', '-f'])
        .reset(['--', 'node_modules/**'])
        .commit(TRAVIS_COMMIT_MESSAGE, () => log('Pushing deployment... Please wait...'))
        .push(['-f', '-q', url, 'HEAD:refs/heads/master'], (err) => {
            if (err) {
                console.log(chalk.bold.magenta(err));
                return exit('An error occurred. Please fix the build and try again.', true);
            }
        })
        .then(() => {
            console.log(chalk.bold.green('Successfully deployed to https://' + AZURE_WA_SITE + '-' + slot + '.azurewebsites.net'))
            process.exit(0);
        });
}
catch (error) {
    exit(error, true);
}

function log(message) {
    console.log(chalk.bold.cyan(message));
}

function exit(reason, abort) {
    if (reason) {
        abort ? console.log(chalk.bold.red(reason)) : console.log(chalk.bold.yellow(reason));
    }

    return abort ? process.exit(1) : process.exit(0);
}<commit_msg>silencing output<commit_after>#!/usr/bin/env node --harmony

let chalk = require('chalk');
let _ = require('lodash');
let { build, config } = require('./env.config');
let git = require('simple-git')();

let {TRAVIS, TRAVIS_BRANCH, TRAVIS_PULL_REQUEST, TRAVIS_COMMIT_MESSAGE, AZURE_WA_USERNAME, AZURE_WA_SITE, AZURE_WA_PASSWORD } = process.env;

log('Deploying commit: ' + TRAVIS_COMMIT_MESSAGE + ' by Travis');

/* Check if the code is running inside of travis.ci. If not abort immediately. */
if (!TRAVIS) {
    exit('Not running inside of Travis. Skipping deploy', true);
}

if (!_.isString(AZURE_WA_USERNAME)) {
    exit('"AZURE_WA_USERNAME" is a required global variable', true);
}

if (!_.isString(AZURE_WA_PASSWORD)) {
    exit('"AZURE_WA_PASSWORD" is a required global variable', true);
}

if (!_.isString(AZURE_WA_SITE)) {
    exit('"AZURE_WA_SITE" is a required global variable', true);
}

/* Check if the branch name is valid. */
let slot = _.isString(TRAVIS_BRANCH) && _.kebabCase(TRAVIS_BRANCH);
if (!slot) {
    exit('Invalid branch name. Skipping deploy', true);
}

switch (slot) {
    case 'master':
        slot = 'edge';
        break;
}

/* Check if there is a configuration defined inside of config/env.config.js. */
let buildConfig = config[slot];
if (buildConfig == null || slot === 'local') {
    exit('No deployment configuration found for ' + slot + '. Skipping deployment.');
}

/* If 'production' then apply the pull request only constraint. */
if (slot === 'production') {
    log('Production Deployment - Pull Request Status: ' + TRAVIS_PULL_REQUEST);
    if (TRAVIS_PULL_REQUEST == false) {
        exit('Deployments to "production" can only be done via pull requests.');
    }
    else {
        slot = 'staging';
    }
}

let url = 'https://'
    + AZURE_WA_USERNAME + ':'
    + AZURE_WA_PASSWORD + '@'
    + AZURE_WA_SITE + '-'
    + slot + '.scm.azurewebsites.net:443/'
    + AZURE_WA_SITE + '.git';

log('Deploying to ' + AZURE_WA_SITE + '-' + slot);

try {
    git.outputHandler((command, stdout) => null)
        .addConfig('user.name', 'Travis CI')
        .addConfig('user.email', 'travis.ci@microsoft.com')
        .checkout('HEAD')
        .add(['.', '-A', '-f', '&>', '/dev/null'])
        .reset(['--', 'node_modules/**'])
        .commit(TRAVIS_COMMIT_MESSAGE, () => log('Pushing deployment... Please wait...'))
        .push(['-f', url, 'HEAD:refs/heads/master', '&>', '/dev/null'], (err) => {
            if (err) {
                return exit('An error occurred. Please fix the build and try again.', true);
            }
        })
        .then(() => {
            console.log(chalk.bold.green('Successfully deployed to https://' + AZURE_WA_SITE + '-' + slot + '.azurewebsites.net'))
            process.exit(0);
        });
}
catch (error) {
    exit(error, true);
}

function log(message) {
    console.log(chalk.bold.cyan(message));
}

function exit(reason, abort) {
    if (reason) {
        abort ? console.log(chalk.bold.red(reason)) : console.log(chalk.bold.yellow(reason));
    }

    return abort ? process.exit(1) : process.exit(0);
}<|endoftext|>


<commit_before>/* jshint node: true */

module.exports = function(deployTarget) {
  var ENV = {
    build: {},
    fireBaseAppName: process.env.FIREBASE_APP_NAME
    // include other plugin configuration that applies to all deploy targets here
  };
  ENV["revision-data"] = {
    type: 'version-commit'
  };
  if (deployTarget === 'development') {
    ENV.build.environment = 'development';
    // configure other plugins for development deploy target here
  }

  if (deployTarget === 'staging') {
    ENV.build.environment = 'production';
    // configure other plugins for staging deploy target here
  }

  if (deployTarget === 'production') {
    ENV.build.environment = 'production';
    // configure other plugins for production deploy target here
  }

  // Note: if you need to build some configuration asynchronously, you can return
  // a promise that resolves with the ENV object instead of returning the
  // ENV object synchronously.
  return ENV;
};
<commit_msg>add staging fb app<commit_after>/* jshint node: true */

module.exports = function(deployTarget) {
  var ENV = {
    build: {},
    fireBaseAppName: process.env.FIREBASE_APP_NAME
    // include other plugin configuration that applies to all deploy targets here
  };
  ENV["revision-data"] = {
    type: 'version-commit'
  };
  if (deployTarget === 'development') {
    ENV.build.environment = 'development';
    // configure other plugins for development deploy target here
  }

  if (deployTarget === 'staging') {
    ENV.build.environment = 'production';
    ENV.fireBaseAppName = 'flowerpot-staging';
    // configure other plugins for staging deploy target here
  }

  if (deployTarget === 'production') {
    ENV.build.environment = 'production';
    // configure other plugins for production deploy target here
  }

  // Note: if you need to build some configuration asynchronously, you can return
  // a promise that resolves with the ENV object instead of returning the
  // ENV object synchronously.
  return ENV;
};
<|endoftext|>


<commit_before>var Index = require('../app/controllers/index')
var User = require('../app/controllers/user')
var Admin = require('../app/controllers/admin')
var Class = require('../app/controllers/class')

module.exports = function(app){

    app.use(function(req,res,next){
        var _user = req.session.user
        app.locals.user = _user
        return next()
    })

    // app.get('/home',Index.index)
    app.post('/',Index.send)

    app.get('/oauth',User.oauth)
    app.get('/',Index.index)
    app.get('/wx/callback',User.callback)
    app.get('/user/login',User.renderLogin)
    app.get('/user/reg',User.renderReg)
    app.get('/user/:openid',User.renderSelfPage)
    app.put('/user',User.updateSelf)
    app.post('/user/reg',User.reg)
    app.post('/user/login',User.login)
    app.get('/logout',User.logout)

    // app.get('/chatroom',Index.renderChatroom)

    // admin start
    app.get('/admin',Admin.renderIndex)
    app.get('/admin/login',Admin.renderLogin)
    app.get('/admin/reg',Admin.renderReg)
    app.post('/admin/user/reg',User.adminReg)
    app.post('/admin/user/login',User.adminLogin)
    app.get('/admin/logout',User.adminLogout)
    app.get('/admin/user/:id',Admin.renderSelfPage)
    app.put('/admin/user/self',Admin.updateSelf)

    app.get('/admin/stu/list',Admin.renderStuList)
    app.get('/admin/stu/update/:id',Admin.renderUpdateStu)
    app.delete('/admin/stu',Admin.delStu)
    app.put('/admin/stu/update',Admin.updateStu)

    app.get('/admin/class/list',Class.renderList)
    app.get('/admin/class/import/:id',Class.renderStuAdd)
    app.get('/admin/class/add',Class.renderAdd)
    app.get('/admin/class/:id',Class.renderClassPage)

    app.post('/admin/class/',Class.addTClass)
    app.delete('/admin/class',Class.del)
    app.get('/admin/class/update/:id',Class.update)
    app.post('/admin/class/add',Class.importStu)

    app.get('/admin/class/:id/chatroom',Class.renderChatroom)
    app.get('/admin/class/:id/realtime',Class.renderRealtime)

    // admin end
}
<commit_msg>update<commit_after>var Index = require('../app/controllers/index')
var User = require('../app/controllers/user')
var Admin = require('../app/controllers/admin')
var Class = require('../app/controllers/class')

module.exports = function(app){

    app.use(function(req,res,next){
        var _user = req.session.user
        app.locals.user = _user
        return next()
    })

    // app.get('/home',Index.index)
    app.post('/',Index.send)

    app.get('/oauth',User.oauth)
    app.get('/',Index.index)
    app.get('/wx/callback',User.callback)
    app.get('/user/login',User.renderLogin)
    app.get('/user/reg',User.renderReg)
    app.get('/user/:openid',User.renderSelfPage)
    app.put('/user',User.updateSelf)
    app.post('/user/reg',User.reg)
    app.post('/user/login',User.login)
    app.get('/logout',User.logout)

    app.get('/chatroom',Index.renderChatroom)

    // admin start
    app.get('/admin',Admin.renderIndex)
    app.get('/admin/login',Admin.renderLogin)
    app.get('/admin/reg',Admin.renderReg)
    app.post('/admin/user/reg',User.adminReg)
    app.post('/admin/user/login',User.adminLogin)
    app.get('/admin/logout',User.adminLogout)
    app.get('/admin/user/:id',Admin.renderSelfPage)
    app.put('/admin/user/self',Admin.updateSelf)

    app.get('/admin/stu/list',Admin.renderStuList)
    app.get('/admin/stu/update/:id',Admin.renderUpdateStu)
    app.delete('/admin/stu',Admin.delStu)
    app.put('/admin/stu/update',Admin.updateStu)

    app.get('/admin/class/list',Class.renderList)
    app.get('/admin/class/import/:id',Class.renderStuAdd)
    app.get('/admin/class/add',Class.renderAdd)
    app.get('/admin/class/:id',Class.renderClassPage)

    app.post('/admin/class/',Class.addTClass)
    app.delete('/admin/class',Class.del)
    app.get('/admin/class/update/:id',Class.update)
    app.post('/admin/class/add',Class.importStu)

    app.get('/admin/class/:id/chatroom',Class.renderChatroom)
    app.get('/admin/class/:id/realtime',Class.renderRealtime)

    // admin end
}
<|endoftext|>


<commit_before>var dir = ('../app/controllers/')
  , main = require(dir + 'main')
  , comments = require(dir + 'comments')
  , posts = require(dir + 'posts')
  , users = require(dir + 'users')
  , admin = require(dir + 'admin')
  , adminPanel = require(dir + 'admin/panel')
  , adminPosts = require(dir + 'admin/posts')
  , adminComments = require(dir + 'admin/comments')
  , adminUsers = require(dir + 'admin/users');

module.exports = function(app) {
  /**
   * Public Routes.
   */
  app.get('/', main.index);
  app.get('/about', main.about);
  app.get('/contact', main.contact);

  app.resource('comments', comments);
  app.get('/comments/:comment/flag', comments.flag);
  app.post('/comments/flag', comments.flag_confirm);

  app.resource('posts', posts);

  app.resource('users', users);
  app.get('/account', users.account);

  /**
   * TODO(dlochrie) This is a temporary admin check, but it needs to be
   * expanded on and refactored.
   *
   * Add authentication middleware to the `admin` namespace.
   */
  app.all('/admin/*', admin.authenticate);

  /**
   * Admin Routes. Should be protected by middleware above.
   */
  app.resource('admin', adminPanel);
  app.resource('admin/posts', adminPosts);
  app.get('/admin/posts/:post/delete', adminPosts.delete);
  app.resource('admin/users', adminUsers);
  app.get('/admin/users/:user/delete', adminUsers.delete);
  app.resource('admin/comments', adminComments);
  app.get('/admin/comments/:comment/delete', adminComments.delete);
  app.get('/admin/comments/:comment/flag', adminComments.flag);
  app.get('/admin/comments/:comment/unflag', adminComments.unflag);
};
<commit_msg>Fixed a wildcard in routes for catching unauthorized access.<commit_after>var dir = ('../app/controllers/')
  , main = require(dir + 'main')
  , comments = require(dir + 'comments')
  , posts = require(dir + 'posts')
  , users = require(dir + 'users')
  , admin = require(dir + 'admin')
  , adminPanel = require(dir + 'admin/panel')
  , adminPosts = require(dir + 'admin/posts')
  , adminComments = require(dir + 'admin/comments')
  , adminUsers = require(dir + 'admin/users');

module.exports = function(app) {
  /**
   * Public Routes.
   */
  app.get('/', main.index);
  app.get('/about', main.about);
  app.get('/contact', main.contact);

  app.resource('comments', comments);
  app.get('/comments/:comment/flag', comments.flag);
  app.post('/comments/flag', comments.flag_confirm);

  app.resource('posts', posts);

  app.resource('users', users);
  app.get('/account', users.account);

  /**
   * TODO(dlochrie) This is a temporary admin check, but it needs to be
   * expanded on and refactored.
   *
   * Add authentication middleware to the `admin` namespace.
   */
  app.all('/admin*', admin.authenticate);

  /**
   * Admin Routes. Should be protected by middleware above.
   */
  app.resource('admin', adminPanel);
  app.resource('admin/posts', adminPosts);
  app.get('/admin/posts/:post/delete', adminPosts.delete);
  app.resource('admin/users', adminUsers);
  app.get('/admin/users/:user/delete', adminUsers.delete);
  app.resource('admin/comments', adminComments);
  app.get('/admin/comments/:comment/delete', adminComments.delete);
  app.get('/admin/comments/:comment/flag', adminComments.flag);
  app.get('/admin/comments/:comment/unflag', adminComments.unflag);
};
<|endoftext|>