<commit_before>function(doc) {

    //tender checks
    var startDate = (doc.enquiryPeriod || {}).startDate;
    if ( (!startDate) || (startDate < "2016-04-01") ) {return;}
    if (doc.procurementMethod !== "open") {return;}
    if ((doc.mode || "") === "test") { return;}

    var bids_disclojure_date = (doc.qualificationPeriod || {}).startDate || (doc.awardPeriod || {}).startDate || null;
    if (!bids_disclojure_date) {return;}

    //global tender values
    var kind = doc.procuringEntity.kind || "_kind";
    var owner = doc.owner;
    var tender_id = doc._id;
    var tender_status = doc.status;
    var tenderID = doc.tenderID;
    var datemodified = doc.dateModified;

    var count_lot_bids = function(lot, bids) {
        return ( bids || [] ).map(function(bid) {
            return ( bid.lotValues || [] ).filter(function(value) {
                return value.relatedLot === lot.id;
            }).length;
        }).reduce(function( total, curr) {
            return total + curr;
        }, 0) || 0;
    };

    var count_lot_qualifications = function(qualifications, lot_id) {
        if ( (typeof qualifications === 'undefined') || (qualifications.length === 0) ) {
            return 0;
        }
        return qualifications.filter(function(qualification) {
            return qualification.lotID === lot_id;
        }).length;
    }

    var max_date = function (obj) {
        //helper function to find max date in object
        var dates = [];

        ['date', 'dateSigned', 'documents'].forEach(function(field){
            var date = obj[field] || '';
            if (date) {
                if (typeof date === "object") {
                    date.forEach(function(d) {
                        dates.push(new Date(d.datePublished));
                    });
                } else {
                    dates.push(new Date(date));
                }
            }
        });
        return new Date(Math.max.apply(null, dates));
    };

    var date_normalize = function(date) {
        //return date in UTC format
        return ((typeof date === 'object') ? date : (new Date(date))).toISOString().slice(0, 23);
    };

    var find_complaint_date = function(complaints) {
        return new Date(Math.max.apply(null, complaints.map(function(c) {
            var d = (c.type === 'claim') ? c.dateAnswered : c.dateDecision;
            if ( (typeof d === 'undefined') || (d === null) ) {
                return null;
            } else {
                return new Date(d);
            }
        }).filter(function(d) {
            return d !== null;
        })));

    };

    var find_cancellation_max_date = function(cancellations) {
        if ((typeof cancellations === 'undefined') || (cancellations.length === 0)) {
            return null;
        }
        if (cancellations.length > 1) {
            return max_date(tender_cancellations.reduce(function(prev_doc, curr_doc) {
                return ( prev_doc.date > curr_doc.date ) ? curr_doc : prev_doc;
            }));
        } else {
            return max_date(cancellations[0]);
        }
    };

    var find_awards_max_date = function(awards) {
        if ((typeof awards === 'undefined') || (awards.length === 0)) {
            return null;
        }
        var date = new Date(Math.max.apply(null, awards.map(function(aw) {
            if('complaints' in aw)  {
                var d = find_complaint_date(aw.complaints);
                if (isNaN(d.getTime())) {
                    return new Date(aw.complaintPeriod.endDate);
                } else {
                    return d;
                }
            } else {
                return new Date(aw.complaintPeriod.endDate);
            }
        })));
        return  date;
    };

    var Handler = function (tender){
        this.status = tender.status;
        this.is_multilot = ( "lots" in tender ) ? true:false;
        this.bids_disclosure_standstill = new Date(bids_disclojure_date);
        if ('date' in tender) {
            if (['complete', 'cancelled', 'unsuccessful'].indexOf(tender.status) !== -1) {
                if (tender.status === 'cancelled') {
                    if ((new Date(tender.date)) < this.bids_disclosure_standstill) {
                        this.tender_date = null;
                    } else {
                        this.tender_date = new Date(tender.date);
                    }
                } else {
                    this.tender_date = new Date(tender.date);
                }
            } else {
                this.tender_date = null;
            }
        } else {
            switch (this.status) {
            case 'complete':
                this.tender_date = new Date( Math.max.apply(null, ( tender.contracts || [] ).filter(function(c) {
                    return c.status === 'active';
                }).map(function(c){
                    return max_date(c);
                })));
                break;
            case 'unsuccessful':
                this.tender_date = find_awards_max_date(tender.awards);
                break;
            case 'cancelled':
                var cancellation_date = find_cancellation_max_date(tender.cancellations.filter(function(cancellation) {
                    return ( (cancellation.status === 'active') && (cancellation.cancellationOf === 'tender') );
                }));
                if (cancellation_date < this.bids_disclosure_standstill) {
                    this.tender_date = null;
                } else {
                    this.tender_date = cancellation_date;
                }
                break;
            default:
                this.tender_date = null;
            } }
    };

    var lotHandler = function (lot, tender){
        this.status = lot.status;
        this.tender_handler = new Handler(tender);
        if ('date' in lot) {
            if (['complete', 'cancelled', 'unsuccessful'].indexOf(lot.status) !== -1) {
                if (this.status === 'cancelled') {
                    if ((new Date(lot.date)) < this.tender_handler.bids_disclosure_standstill) {
                        this.lot_date = null;
                    } else {
                        this.lot_date = new Date(lot.date);
                    }
                } else {
                    this.lot_date = new Date(lot.date);
                }
            } else {
                if (this.tender_handler.status === 'cancelled') {
                    this.lot_date = (this.tender_handler.tender_date !== null) ? this.tender_handler.tender_date : null;
                } else {
                    this.lot_date = null;
                }
            }
        } else {
            switch(this.status) {
            case 'unsuccessful':
                this.lot_date = find_awards_max_date(( tender.awards || [] ).filter(function(award) {
                    return award.lotID === lot.id;
                }));
                break;
            case 'cancelled':
                var lot_cancellation = find_cancellation_max_date(tender.cancellations.filter(function(cancellation) {
                    return (cancellation.status === 'active') && (cancellation.cancellationOf === 'lot') && (cancellation.relatedLot === lot.id);
                }));
                if ((lot_cancellation !== null) && (lot_cancellation > this.tender_handler.bids_disclosure_standstill)) {
                    this.lot_date = lot_cancellation;
                } else {
                    this.lot_date = null;
                }
                 break;
            case 'complete':

                var contract_date = '';
                tender.awards.forEach(function(award) {
                    if (award.lotID === lot.id) {
                        (tender.contracts || []).forEach(function(contract) {
                            if (award.id === contract.awardID) {
                                if (contract.status === 'active') {
                                   contract_date = max_date(contract);
                                }
                            }
                        });
                    }
                });
                this.lot_date = contract_date || null;
                break;
            default:
            if (tender.status === 'cancelled') {
                    if (this.tender_handler.tender_date !== null) {
                        if ( this.tender_handler.tender_date > this.tender_handler.bids_disclosure_standstill) {
                            this.lot_date = this.tender_handler.tender_date;
                        }
                    } else {
                        this.lot_date = null;
                    }
                } else {
                    var lotDate = '';
                    ( tender.awards || [] ).forEach(function(award) {
                        if (award.lotID === lot.id) {
                            (tender.contracts || []).forEach(function(contract) {
                                if (award.id === contract.awardID) {
                                    if (contract.status === 'active') {
                                        lotDate = max_date(contract);
                                    }
                                }
                            });
                        }
                    });
                    this.lot_date = lotDate || null;
                }
        } }
    }; // lotHandle

    var emitter = {
        lot: function(lot, date) {
            emit([owner, date_normalize(date), lot.id], {
                tender: tender_id,
                lot: lot.id,
                value: lot.value.amount,
                currency: lot.value.currency,
                kind: kind,
                lot_status: lot.status,
                status: tender_status,
                datemodified: datemodified,
                startdate: startDate,
                tenderID: tenderID,
            });
        },
        tender: function(tender,date) {
            emit([owner, date_normalize(date)], {
                tender: tender_id,
                value: tender.value.amount,
                currency: tender.value.currency,
                kind: kind,
                status: tender_status,
                datemodified: datemodified,
                startdate: startDate,
                tenderID: tenderID,
            });
        }
    };

    var check_lot = function(lot, tender) {

        if ( tender.procurementMethodType === 'aboveThresholdUA' ) {
            if (count_lot_bids(lot, tender.bids) > 1) {
                return true;
            }
        } else if (tender.procurementMethodType === 'aboveThresholdEU') {
            if (count_lot_qualifications(tender.qualifications, lot.id) > 1) {
                return true;
            }

        } else if (tender.procurementMethodType === 'aboveThresholdUA.defense') {
            var lot_awards = ('awards' in tender) ? (
                tender.awards.filter(function(a) {
                    return a.lotID === lot.id;
                })
            ) : [];
            if ( ( (count_lot_bids(lot, tender.bids) < 2 ) && (lot_awards.length === 0))) {
                return false;
            } else {
                return true;
            }
        } else {
            if (count_lot_bids(lot, tender.bids) > 0) {
                return true;
            }
        }
        return false;
    };

    var check_tender = function(tender) {
        if ( tender.procurementMethodType === 'aboveThresholdUA' ) {
            if (tender.numberOfBids > 1) {
                return true;
            }
        } else if (tender.procurementMethodType === 'aboveThresholdEU') {
            if (tender.qualifications.length > 1) {
                return true;
            }

        } else if (tender.procurementMethodType === 'aboveThresholdUA.defense') {
            if( (tender.numberOfBids < 2) && !('awards' in tender)) {
                log('skip tender '+tender.id + " bids: "+ tender.numberOfBids);
                return false;
            } else {
                return true;
            }
        } else {
            if (tender.numberOfBids > 0) {
                return true;
            }
        }
        return false;
    };

    var find_tender_data = function(tender) {
        var handler = new Handler(tender);
        if (handler.is_multilot) {
            tender.lots.forEach(function(lot){
                if ( check_lot(lot, tender) ) {
                    var lot_handler = new lotHandler(lot, tender);
                    if (lot_handler.lot_date !== null) {
                        emitter.lot(lot, lot_handler.lot_date);
                    }
                }
            });

        } else {

            if (check_tender(tender)) {
                if (tender.status === 'cancelled') {
                    if (handler.tender_date < handler.bids_disclosure_standstill) { return; }
                }
                if (handler.tender_date !==  null) {
                    emitter.tender(tender, handler.tender_date);
                }
            }
        }
    };

    find_tender_data(doc);
}// end function

<commit_msg>Handle tenders without qualifications<commit_after>function(doc) {

    //tender checks
    var startDate = (doc.enquiryPeriod || {}).startDate;
    if ( (!startDate) || (startDate < "2016-04-01") ) {return;}
    if (doc.procurementMethod !== "open") {return;}
    if ((doc.mode || "") === "test") { return;}

    var bids_disclojure_date = (doc.qualificationPeriod || {}).startDate || (doc.awardPeriod || {}).startDate || null;
    if (!bids_disclojure_date) {return;}

    //global tender values
    var kind = doc.procuringEntity.kind || "_kind";
    var owner = doc.owner;
    var tender_id = doc._id;
    var tender_status = doc.status;
    var tenderID = doc.tenderID;
    var datemodified = doc.dateModified;

    var count_lot_bids = function(lot, bids) {
        return ( bids || [] ).map(function(bid) {
            return ( bid.lotValues || [] ).filter(function(value) {
                return value.relatedLot === lot.id;
            }).length;
        }).reduce(function( total, curr) {
            return total + curr;
        }, 0) || 0;
    };

    var count_lot_qualifications = function(qualifications, lot_id) {
        if ( (typeof qualifications === 'undefined') || (qualifications.length === 0) ) {
            return 0;
        }
        return qualifications.filter(function(qualification) {
            return qualification.lotID === lot_id;
        }).length;
    }

    var max_date = function (obj) {
        //helper function to find max date in object
        var dates = [];

        ['date', 'dateSigned', 'documents'].forEach(function(field){
            var date = obj[field] || '';
            if (date) {
                if (typeof date === "object") {
                    date.forEach(function(d) {
                        dates.push(new Date(d.datePublished));
                    });
                } else {
                    dates.push(new Date(date));
                }
            }
        });
        return new Date(Math.max.apply(null, dates));
    };

    var date_normalize = function(date) {
        //return date in UTC format
        return ((typeof date === 'object') ? date : (new Date(date))).toISOString().slice(0, 23);
    };

    var find_complaint_date = function(complaints) {
        return new Date(Math.max.apply(null, complaints.map(function(c) {
            var d = (c.type === 'claim') ? c.dateAnswered : c.dateDecision;
            if ( (typeof d === 'undefined') || (d === null) ) {
                return null;
            } else {
                return new Date(d);
            }
        }).filter(function(d) {
            return d !== null;
        })));

    };

    var find_cancellation_max_date = function(cancellations) {
        if ((typeof cancellations === 'undefined') || (cancellations.length === 0)) {
            return null;
        }
        if (cancellations.length > 1) {
            return max_date(tender_cancellations.reduce(function(prev_doc, curr_doc) {
                return ( prev_doc.date > curr_doc.date ) ? curr_doc : prev_doc;
            }));
        } else {
            return max_date(cancellations[0]);
        }
    };

    var find_awards_max_date = function(awards) {
        if ((typeof awards === 'undefined') || (awards.length === 0)) {
            return null;
        }
        var date = new Date(Math.max.apply(null, awards.map(function(aw) {
            if('complaints' in aw)  {
                var d = find_complaint_date(aw.complaints);
                if (isNaN(d.getTime())) {
                    return new Date(aw.complaintPeriod.endDate);
                } else {
                    return d;
                }
            } else {
                return new Date(aw.complaintPeriod.endDate);
            }
        })));
        return  date;
    };

    var Handler = function (tender){
        this.status = tender.status;
        this.is_multilot = ( "lots" in tender ) ? true:false;
        this.bids_disclosure_standstill = new Date(bids_disclojure_date);
        if ('date' in tender) {
            if (['complete', 'cancelled', 'unsuccessful'].indexOf(tender.status) !== -1) {
                if (tender.status === 'cancelled') {
                    if ((new Date(tender.date)) < this.bids_disclosure_standstill) {
                        this.tender_date = null;
                    } else {
                        this.tender_date = new Date(tender.date);
                    }
                } else {
                    this.tender_date = new Date(tender.date);
                }
            } else {
                this.tender_date = null;
            }
        } else {
            switch (this.status) {
            case 'complete':
                this.tender_date = new Date( Math.max.apply(null, ( tender.contracts || [] ).filter(function(c) {
                    return c.status === 'active';
                }).map(function(c){
                    return max_date(c);
                })));
                break;
            case 'unsuccessful':
                this.tender_date = find_awards_max_date(tender.awards);
                break;
            case 'cancelled':
                var cancellation_date = find_cancellation_max_date(tender.cancellations.filter(function(cancellation) {
                    return ( (cancellation.status === 'active') && (cancellation.cancellationOf === 'tender') );
                }));
                if (cancellation_date < this.bids_disclosure_standstill) {
                    this.tender_date = null;
                } else {
                    this.tender_date = cancellation_date;
                }
                break;
            default:
                this.tender_date = null;
            } }
    };

    var lotHandler = function (lot, tender){
        this.status = lot.status;
        this.tender_handler = new Handler(tender);
        if ('date' in lot) {
            if (['complete', 'cancelled', 'unsuccessful'].indexOf(lot.status) !== -1) {
                if (this.status === 'cancelled') {
                    if ((new Date(lot.date)) < this.tender_handler.bids_disclosure_standstill) {
                        this.lot_date = null;
                    } else {
                        this.lot_date = new Date(lot.date);
                    }
                } else {
                    this.lot_date = new Date(lot.date);
                }
            } else {
                if (this.tender_handler.status === 'cancelled') {
                    this.lot_date = (this.tender_handler.tender_date !== null) ? this.tender_handler.tender_date : null;
                } else {
                    this.lot_date = null;
                }
            }
        } else {
            switch(this.status) {
            case 'unsuccessful':
                this.lot_date = find_awards_max_date(( tender.awards || [] ).filter(function(award) {
                    return award.lotID === lot.id;
                }));
                break;
            case 'cancelled':
                var lot_cancellation = find_cancellation_max_date(tender.cancellations.filter(function(cancellation) {
                    return (cancellation.status === 'active') && (cancellation.cancellationOf === 'lot') && (cancellation.relatedLot === lot.id);
                }));
                if ((lot_cancellation !== null) && (lot_cancellation > this.tender_handler.bids_disclosure_standstill)) {
                    this.lot_date = lot_cancellation;
                } else {
                    this.lot_date = null;
                }
                 break;
            case 'complete':

                var contract_date = '';
                tender.awards.forEach(function(award) {
                    if (award.lotID === lot.id) {
                        (tender.contracts || []).forEach(function(contract) {
                            if (award.id === contract.awardID) {
                                if (contract.status === 'active') {
                                   contract_date = max_date(contract);
                                }
                            }
                        });
                    }
                });
                this.lot_date = contract_date || null;
                break;
            default:
            if (tender.status === 'cancelled') {
                    if (this.tender_handler.tender_date !== null) {
                        if ( this.tender_handler.tender_date > this.tender_handler.bids_disclosure_standstill) {
                            this.lot_date = this.tender_handler.tender_date;
                        }
                    } else {
                        this.lot_date = null;
                    }
                } else {
                    var lotDate = '';
                    ( tender.awards || [] ).forEach(function(award) {
                        if (award.lotID === lot.id) {
                            (tender.contracts || []).forEach(function(contract) {
                                if (award.id === contract.awardID) {
                                    if (contract.status === 'active') {
                                        lotDate = max_date(contract);
                                    }
                                }
                            });
                        }
                    });
                    this.lot_date = lotDate || null;
                }
        } }
    }; // lotHandle

    var emitter = {
        lot: function(lot, date) {
            emit([owner, date_normalize(date), lot.id], {
                tender: tender_id,
                lot: lot.id,
                value: lot.value.amount,
                currency: lot.value.currency,
                kind: kind,
                lot_status: lot.status,
                status: tender_status,
                datemodified: datemodified,
                startdate: startDate,
                tenderID: tenderID,
            });
        },
        tender: function(tender,date) {
            emit([owner, date_normalize(date)], {
                tender: tender_id,
                value: tender.value.amount,
                currency: tender.value.currency,
                kind: kind,
                status: tender_status,
                datemodified: datemodified,
                startdate: startDate,
                tenderID: tenderID,
            });
        }
    };

    var check_lot = function(lot, tender) {

        if ( tender.procurementMethodType === 'aboveThresholdUA' ) {
            if (count_lot_bids(lot, tender.bids) > 1) {
                return true;
            }
        } else if (tender.procurementMethodType === 'aboveThresholdEU') {
            if (count_lot_qualifications(tender.qualifications, lot.id) > 1) {
                return true;
            }

        } else if (tender.procurementMethodType === 'aboveThresholdUA.defense') {
            var lot_awards = ('awards' in tender) ? (
                tender.awards.filter(function(a) {
                    return a.lotID === lot.id;
                })
            ) : [];
            if ( ( (count_lot_bids(lot, tender.bids) < 2 ) && (lot_awards.length === 0))) {
                return false;
            } else {
                return true;
            }
        } else {
            if (count_lot_bids(lot, tender.bids) > 0) {
                return true;
            }
        }
        return false;
    };

    var check_tender = function(tender) {
        if ( tender.procurementMethodType === 'aboveThresholdUA' ) {
            if (tender.numberOfBids > 1) {
                return true;
            }
        } else if (tender.procurementMethodType === 'aboveThresholdEU') {
            if ( ( tender.qualifications.length || []) > 1) {
                return true;
            }

        } else if (tender.procurementMethodType === 'aboveThresholdUA.defense') {
            if( (tender.numberOfBids < 2) && !('awards' in tender)) {
                log('skip tender '+tender.id + " bids: "+ tender.numberOfBids);
                return false;
            } else {
                return true;
            }
        } else {
            if (tender.numberOfBids > 0) {
                return true;
            }
        }
        return false;
    };

    var find_tender_data = function(tender) {
        var handler = new Handler(tender);
        if (handler.is_multilot) {
            tender.lots.forEach(function(lot){
                if ( check_lot(lot, tender) ) {
                    var lot_handler = new lotHandler(lot, tender);
                    if (lot_handler.lot_date !== null) {
                        emitter.lot(lot, lot_handler.lot_date);
                    }
                }
            });

        } else {

            if (check_tender(tender)) {
                if (tender.status === 'cancelled') {
                    if (handler.tender_date < handler.bids_disclosure_standstill) { return; }
                }
                if (handler.tender_date !==  null) {
                    emitter.tender(tender, handler.tender_date);
                }
            }
        }
    };

    find_tender_data(doc);
}// end function

<|endoftext|>


<commit_before>//v1.0 as Starting Point
//v2.0 Cleaning up code. Setting up Menu Structure and Initial Settings and functions.

var version = '2.1';
var SCBversion = '3.05'; //Last SandCastle Builder version tested

//Declare and Initialize Variables
var incoming_ONG = 0;
var NinjaAutoClickStatus = 1;
var Time_to_ONG = 1800000;
var lootBoxes = ['boosts', 'ninj', 'cyb', 'hpt', 'bean', 'chron', 'badges', 'badgesav'];

//BB Options Variables
var AudioAlertsStatus = 3;
var audio_Bell = new Audio("http://xenko.comxa.com/Ship_Bell.mp3");
	audio_Bell.volume = 1;
var audio_Chime = new Audio("http://xenko.comxa.com/Chime.mp3");
	audio_Chime.volume = 1;
var BorderAlertStatus = 1;
var description = "Error";
var refreshRate = 1000;
var RKAlertFrequency = 8;
var RKAutoClickStatus = 1;
var RKPlayAudio = 1;

//RK Variables
var start = -1;
var content = "empty";
var LCAutoClickStatus = 0;
var LCSolution = 'blank';
var len = 0;
var Logicat = 0;
var oldRKLocation = -1;
var oldRC = Molpy.redactedClicks - 1;
var oldLC = Molpy.Boosts['Logicat'].power - 1;
var RKLevel = '-1';
var RKLocation = '123';
var RKNew = 1;
var RKNewAudio = 1;
var RKTimer = Molpy.redactedToggle - Molpy.redactedCountup;

function BClick(){
	if (Molpy.Got('Temporal Rift') && Molpy.Boosts['Temporal Rift'].countdown < 5){
		//Do Nothing to avoid temporal rift
	}
	else {
		Molpy.ClickBeach();
	}
}

function Ninja() {
    if (Molpy.ninjad == 0) {
        if (Molpy.npbONG == 0 && BorderAlertStatus == 1) {
			$("#beach").css("border","4px solid red");
        }
        else {
            incoming_ONG = 0;
            if (NinjaAutoClickStatus == 1) {
				BClick();
				Molpy.Notify('Ninja Auto Click', 1);
				if (BorderAlertStatus == 1) {
					$("#beach").css("border","2px solid green");
				}
            }
            else if (BorderAlertStatus == 1) {
            $("#beach").css("border","4px solid blue");
            }

        }
	}
    else if (Time_to_ONG <= 15000) {
		if (BorderAlertStatus == 1) {
			$("#beach").css("border","4px solid yellow");
		}
        if (incoming_ONG == 0 && (AudioAlertsStatus == 3 || AudioAlertsStatus == 4)) {
			audio_Chime.play();
			incoming_ONG = 1;
        }
    }
    else if (BorderAlertStatus == 1) {
        $("#beach").css("border","2px solid green");
	}
}

function ToggleMenus(wantOpen) {
	for (i=0, len = lootBoxes.length; i < len; i++) {
		if (lootBoxes[i] == wantOpen) {
			if (Molpy.options.showhide[lootBoxes[i]] != 1) {
				showhideToggle(lootBoxes[i]);
			}
		}
		else {
			if (Molpy.options.showhide[lootBoxes[i]]) {
				showhideToggle(lootBoxes[i]);
			}
		}
	}
}

function FindRK() {
	/*
	RV of 1 is Sand Tools
	RV of 2 is Castle Tools
	RV of 3 is Boosts Main Page
	RV of 4 is Boosts Menus, Hill People Tech, etc.
	RV of 5 is Badges Earned
	RV of 6 is Badges Available
	*/

	//Determines RK location
	RKLocation = '123';
	if (Molpy.redactedVisible == 6) {
		RKLocation = 'badgesav';
	}
	else if (Molpy.redactedVisible > 3) {
		RKLocation = Molpy.redactedGr;
	}

	//Opens RK location
	ToggleMenus(RKLocation);

	//Resets old RK variables
	oldRKLocation = Molpy.redactedVisible;
	oldRC = Molpy.redactedClicks;
	oldLC = Molpy.Boosts['Logicat'].power;
}

function ManualRKClick() {

}

function RedundaKitty() {
	//Refresh Timer Variable
	RKTimer = Molpy.redactedToggle - Molpy.redactedCountup;

	//If a RedundaKitty is active
	if (Molpy.redactedVisible > 0) {

		//Checks if RK is new
		if (RKNew == 1 || Molpy.redactedVisible != oldRKLocation || Molpy.redactedClicks > oldRC || Molpy.Boosts['Logicat'].power != oldLC) {
			RKNewAudio = 1;
			RKNew = 0;
			//Finds RK if appropriate BeachBall option enabled
			if (RKAutoClickStatus > 0) {
				FindRK();
			}
		}

		//Determines if it is an RK or LC
		//If RK is visible
		if ($('#redacteditem').length) {
			$('#redacteditem').css("border","2px solid red"); //Highlights RK
			content = $('#redacteditem').html();
			//If RK contains word statement, it is a LC.
			if (content.indexOf("statement") !== -1) {
				Logicat = 1;
			}
			//Otherwise it is an RK
			else {
				Logicat = 0;
				if (content.indexOf("Show") != -1) {
					start = content.indexOf("Show");
					content = content.substring(start+15,start+38);
					content = content.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g,'');
					len = content.length;
					RKLevel = content.substring(18,len);
					//Molpy.Notify('RedundaKitty Level is: ' + RKLevel, 1);
				}
				else {
					start = content.indexOf("iframe src=");
					content = content.substring(start-40,start-16);
					content = content.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g,'');
					len = content.length;
					RKLevel = content.substring(18,len);
					//Molpy.Notify('YT RedundaKitty Level is: ' + RKLevel, 1);
				}
			}
		}
		//If RK not visible, LC to 99.
		else {
			Logicat = 99;
		}

		//Clicks RK if AutoClick Enabled
		if (RKAutoClickStatus == 2 && Logicat == 0 ) {
			Molpy.ClickRedacted(RKLevel);
			RKNew = 1;
			RKLocation = '123';
			ToggleMenus('123');
		}
		//Solves LC if AutoClick enabled
		else if (Logicat == 1 && LCAutoClickStatus == 1) {
			SolveLogicat();
			RKNew = 1;
			RKLocation = '123';
			ToggleMenus('123');
		}

		//Redundakitty Notifications for Manual Clicking (Title Bar, Audio)
		else {
			document.title = "! kitten !";
			//If RK Audio Alerts Enabled
			if (AudioAlertsStatus == 1 || AudioAlertsStatus == 3) {
				//If proper mNP and hasn't yet played this mNP
				if (Math.floor(RKTimer % RKAlertFrequency) == 0 && RKPlayAudio == 1) {
					audio_Bell.play();
					RKPlayAudio = 0;
				}
				else {
					RKPlayAudio = 1;
				}
			}
		}
	}
	//If no RK active, update title Timer. Reset some variables.
	else {
		document.title = RKTimer;
		oldRKLocation = -1;
		RKNew = 1;
		RKPlayAudio = 0;
	}
}

function SolveLogicat() {
	var i = 65;
	do
		{LCSolution = String.fromCharCode(i);
		i++;}
	while (Molpy.redactedPuzzleTarget != Molpy.redactedSGen.StatementValue(LCSolution));
	Molpy.ClickRedactedPuzzle(LCSolution);
}

function SwitchOption(option) {
	switch (option) {
		case 'RKAutoClick':
			RKAutoClickStatus++;
			if (RKAutoClickStatus > 2) {RKAutoClickStatus = 0;}
			status = RKAutoClickStatus;
			break;
		case 'LCAutoClick':
			LCAutoClickStatus++;
			if (LCAutoClickStatus > 1) {LCAutoClickStatus = 0;}
			status = LCAutoClickStatus;
			break;
		case 'NinjaAutoClick':
			NinjaAutoClickStatus++;
			if (NinjaAutoClickStatus > 1) {NinjaAutoClickStatus = 0;}
			status = NinjaAutoClickStatus;
			break;
		case 'BorderAlert':
			BorderAlertStatus++;
			if (BorderAlertStatus > 1) {
				BorderAlertStatus = 0;
				$("#beach").css("border","1px solid white");
			}
			status = BorderAlertStatus;
			break;
		case 'AudioAlerts':
			AudioAlertsStatus++;
			if (AudioAlertsStatus > 3) {AudioAlertsStatus = 0;}
			status = AudioAlertsStatus;
			break;
		case 'RefreshRate':
			newRate = parseInt(prompt('Please enter your desired BeachBall refresh rate in milliseconds (500 - 3600):', refreshRate));
			if (newRate < 500 || newRate > 3600 || isNaN(newRate)){
				Molpy.Notify('Invalid Refresh Rate', 1);
			}
			else {
				refreshRate = newRate;
			}
			break;
	}
	DisplayDescription(option, status);
}

function DisplayDescription(option, status) {
	error = 0;
	if (option == 'LCAutoClick' || option == 'NinjaAutoClick' || option == 'BorderAlert') {
		if (status == 0) {description = 'Off';}
		else if (status == 1) {description = 'On';}
		else {Molpy.Notify('Display Description Error', 1);}
	}
	else if (option == 'AudioAlerts') {
		if (status == 0) {description = 'Off';}
		else if (status == 1) {description = 'RK Only'; RKPlayAudio = 1;}
		else if (status == 2) {description = 'ONG Only';}
		else if (status == 3) {description = 'RK and ONG'; RKPlayAudio = 1;}
		else {Molpy.Notify('Display Description Error - Audio Alerts: ' + status, 1);}
	}
	else if (option == 'RKAutoClick') {
		if (status == 0) {description = 'Off';}
		else if (status == 1) {description = 'Find RK Only'; RKNew = 1;}
		else if (status == 2) {description = 'On'; RKNew = 1;}
		else {Molpy.Notify('Display Description Error - RKAutoClick: ' + status, 1);}
	}
	else if (option == 'RefreshRate') {
		description = refreshRate;
	}
	else {
		Molpy.Notify(option + ' is not a valid option.', 1);
		error = 1;
	}

	if (error == 0) {g(option + 'Desc').innerHTML = '
' + description;}
}

//Beach Ball Startup
//Set Settings
if (Molpy.Got('Kitnip') == 1){RKAlertFrequency = 10;}

//Create Menu
$('#optionsItems').append('

BeachBall Settings

v ' + version + '

');
$('#optionsItems').append('

Redundakitty Auto Click

');
$('#optionsItems').append('

Logicat Auto Click

');
$('#optionsItems').append('

Ninja Auto Click

');
$('#optionsItems').append('

Ninja Visual Alert

');
$('#optionsItems').append('

Audio Alerts

');
$('#optionsItems').append('

Refresh Rate

');
//$('#optionsItems').append('

Spawn RK

');
//$('#optionsItems').append('

Extend RK

');
DisplayDescription('RKAutoClick', RKAutoClickStatus);
DisplayDescription('LCAutoClick', LCAutoClickStatus);
DisplayDescription('NinjaAutoClick', NinjaAutoClickStatus);
DisplayDescription('BorderAlert', BorderAlertStatus);
DisplayDescription('AudioAlerts', AudioAlertsStatus);
DisplayDescription('RefreshRate', refreshRate);

Molpy.Notify('BeachBall version ' + version + ' loaded for SandCastle Builder version ' + SCBversion, 1);
Loop();

function MainProgram() {
	Time_to_ONG = (Molpy.NPlength * 1000) - Molpy.ONGelapsed;
	RedundaKitty();
	Ninja();
	Loop();
}

function Loop() {
	setTimeout(MainProgram, refreshRate);
}
/*
function SpawnRK() {
	Molpy.redactedCountup = Molpy.redactedToggle - 1;
}

function ExtendRK() {
	Molpy.redactedCountup = 1;
}
*/
<commit_msg>Adding main BeachBall.js file<commit_after>var version = '2.1';
var SCBversion = '3.05'; //Last SandCastle Builder version tested

//Declare and Initialize Variables
var incoming_ONG = 0;
var NinjaAutoClickStatus = 1;
var Time_to_ONG = 1800000;
var lootBoxes = ['boosts', 'ninj', 'cyb', 'hpt', 'bean', 'chron', 'badges', 'badgesav'];

//BB Options Variables
var AudioAlertsStatus = 3;
var audio_Bell = new Audio("http://xenko.comxa.com/Ship_Bell.mp3");
	audio_Bell.volume = 1;
var audio_Chime = new Audio("http://xenko.comxa.com/Chime.mp3");
	audio_Chime.volume = 1;
var BorderAlertStatus = 1;
var description = "Error";
var refreshRate = 1000;
var RKAlertFrequency = 8;
var RKAutoClickStatus = 1;
var RKPlayAudio = 1;

//RK Variables
var start = -1;
var content = "empty";
var LCAutoClickStatus = 0;
var LCSolution = 'blank';
var len = 0;
var Logicat = 0;
var oldRKLocation = -1;
var oldRC = Molpy.redactedClicks - 1;
var oldLC = Molpy.Boosts['Logicat'].power - 1;
var RKLevel = '-1';
var RKLocation = '123';
var RKNew = 1;
var RKNewAudio = 1;
var RKTimer = Molpy.redactedToggle - Molpy.redactedCountup;

function BClick(){
	if (Molpy.Got('Temporal Rift') && Molpy.Boosts['Temporal Rift'].countdown < 5){
		//Do Nothing to avoid temporal rift
	}
	else {
		Molpy.ClickBeach();
	}
}

function Ninja() {
    if (Molpy.ninjad == 0) {
        if (Molpy.npbONG == 0 && BorderAlertStatus == 1) {
			$("#beach").css("border","4px solid red");
        }
        else {
            incoming_ONG = 0;
            if (NinjaAutoClickStatus == 1) {
				BClick();
				Molpy.Notify('Ninja Auto Click', 1);
				if (BorderAlertStatus == 1) {
					$("#beach").css("border","2px solid green");
				}
            }
            else if (BorderAlertStatus == 1) {
            $("#beach").css("border","4px solid blue");
            }

        }
	}
    else if (Time_to_ONG <= 15000) {
		if (BorderAlertStatus == 1) {
			$("#beach").css("border","4px solid yellow");
		}
        if (incoming_ONG == 0 && (AudioAlertsStatus == 3 || AudioAlertsStatus == 4)) {
			audio_Chime.play();
			incoming_ONG = 1;
        }
    }
    else if (BorderAlertStatus == 1) {
        $("#beach").css("border","2px solid green");
	}
}

function ToggleMenus(wantOpen) {
	for (i=0, len = lootBoxes.length; i < len; i++) {
		if (lootBoxes[i] == wantOpen) {
			if (Molpy.options.showhide[lootBoxes[i]] != 1) {
				showhideToggle(lootBoxes[i]);
			}
		}
		else {
			if (Molpy.options.showhide[lootBoxes[i]]) {
				showhideToggle(lootBoxes[i]);
			}
		}
	}
}

function FindRK() {
	/*
	RV of 1 is Sand Tools
	RV of 2 is Castle Tools
	RV of 3 is Boosts Main Page
	RV of 4 is Boosts Menus, Hill People Tech, etc.
	RV of 5 is Badges Earned
	RV of 6 is Badges Available
	*/

	//Determines RK location
	RKLocation = '123';
	if (Molpy.redactedVisible == 6) {
		RKLocation = 'badgesav';
	}
	else if (Molpy.redactedVisible > 3) {
		RKLocation = Molpy.redactedGr;
	}

	//Opens RK location
	ToggleMenus(RKLocation);

	//Resets old RK variables
	oldRKLocation = Molpy.redactedVisible;
	oldRC = Molpy.redactedClicks;
	oldLC = Molpy.Boosts['Logicat'].power;
}

function ManualRKClick() {

}

function RedundaKitty() {
	//Refresh Timer Variable
	RKTimer = Molpy.redactedToggle - Molpy.redactedCountup;

	//If a RedundaKitty is active
	if (Molpy.redactedVisible > 0) {

		//Checks if RK is new
		if (RKNew == 1 || Molpy.redactedVisible != oldRKLocation || Molpy.redactedClicks > oldRC || Molpy.Boosts['Logicat'].power != oldLC) {
			RKNewAudio = 1;
			RKNew = 0;
			//Finds RK if appropriate BeachBall option enabled
			if (RKAutoClickStatus > 0) {
				FindRK();
			}
		}

		//Determines if it is an RK or LC
		//If RK is visible
		if ($('#redacteditem').length) {
			$('#redacteditem').css("border","2px solid red"); //Highlights RK
			content = $('#redacteditem').html();
			//If RK contains word statement, it is a LC.
			if (content.indexOf("statement") !== -1) {
				Logicat = 1;
			}
			//Otherwise it is an RK
			else {
				Logicat = 0;
				if (content.indexOf("Show") != -1) {
					start = content.indexOf("Show");
					content = content.substring(start+15,start+38);
					content = content.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g,'');
					len = content.length;
					RKLevel = content.substring(18,len);
					//Molpy.Notify('RedundaKitty Level is: ' + RKLevel, 1);
				}
				else {
					start = content.indexOf("iframe src=");
					content = content.substring(start-40,start-16);
					content = content.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g,'');
					len = content.length;
					RKLevel = content.substring(18,len);
					//Molpy.Notify('YT RedundaKitty Level is: ' + RKLevel, 1);
				}
			}
		}
		//If RK not visible, LC to 99.
		else {
			Logicat = 99;
		}

		//Clicks RK if AutoClick Enabled
		if (RKAutoClickStatus == 2 && Logicat == 0 ) {
			Molpy.ClickRedacted(RKLevel);
			RKNew = 1;
			RKLocation = '123';
			ToggleMenus('123');
		}
		//Solves LC if AutoClick enabled
		else if (Logicat == 1 && LCAutoClickStatus == 1) {
			SolveLogicat();
			RKNew = 1;
			RKLocation = '123';
			ToggleMenus('123');
		}

		//Redundakitty Notifications for Manual Clicking (Title Bar, Audio)
		else {
			document.title = "! kitten !";
			//If RK Audio Alerts Enabled
			if (AudioAlertsStatus == 1 || AudioAlertsStatus == 3) {
				//If proper mNP and hasn't yet played this mNP
				if (Math.floor(RKTimer % RKAlertFrequency) == 0 && RKPlayAudio == 1) {
					audio_Bell.play();
					RKPlayAudio = 0;
				}
				else {
					RKPlayAudio = 1;
				}
			}
		}
	}
	//If no RK active, update title Timer. Reset some variables.
	else {
		document.title = RKTimer;
		oldRKLocation = -1;
		RKNew = 1;
		RKPlayAudio = 0;
	}
}

function SolveLogicat() {
	var i = 65;
	do
		{LCSolution = String.fromCharCode(i);
		i++;}
	while (Molpy.redactedPuzzleTarget != Molpy.redactedSGen.StatementValue(LCSolution));
	Molpy.ClickRedactedPuzzle(LCSolution);
}

function SwitchOption(option) {
	switch (option) {
		case 'RKAutoClick':
			RKAutoClickStatus++;
			if (RKAutoClickStatus > 2) {RKAutoClickStatus = 0;}
			status = RKAutoClickStatus;
			break;
		case 'LCAutoClick':
			LCAutoClickStatus++;
			if (LCAutoClickStatus > 1) {LCAutoClickStatus = 0;}
			status = LCAutoClickStatus;
			break;
		case 'NinjaAutoClick':
			NinjaAutoClickStatus++;
			if (NinjaAutoClickStatus > 1) {NinjaAutoClickStatus = 0;}
			status = NinjaAutoClickStatus;
			break;
		case 'BorderAlert':
			BorderAlertStatus++;
			if (BorderAlertStatus > 1) {
				BorderAlertStatus = 0;
				$("#beach").css("border","1px solid white");
			}
			status = BorderAlertStatus;
			break;
		case 'AudioAlerts':
			AudioAlertsStatus++;
			if (AudioAlertsStatus > 3) {AudioAlertsStatus = 0;}
			status = AudioAlertsStatus;
			break;
		case 'RefreshRate':
			newRate = parseInt(prompt('Please enter your desired BeachBall refresh rate in milliseconds (500 - 3600):', refreshRate));
			if (newRate < 500 || newRate > 3600 || isNaN(newRate)){
				Molpy.Notify('Invalid Refresh Rate', 1);
			}
			else {
				refreshRate = newRate;
			}
			break;
	}
	DisplayDescription(option, status);
}

function DisplayDescription(option, status) {
	error = 0;
	if (option == 'LCAutoClick' || option == 'NinjaAutoClick' || option == 'BorderAlert') {
		if (status == 0) {description = 'Off';}
		else if (status == 1) {description = 'On';}
		else {Molpy.Notify('Display Description Error', 1);}
	}
	else if (option == 'AudioAlerts') {
		if (status == 0) {description = 'Off';}
		else if (status == 1) {description = 'RK Only'; RKPlayAudio = 1;}
		else if (status == 2) {description = 'ONG Only';}
		else if (status == 3) {description = 'RK and ONG'; RKPlayAudio = 1;}
		else {Molpy.Notify('Display Description Error - Audio Alerts: ' + status, 1);}
	}
	else if (option == 'RKAutoClick') {
		if (status == 0) {description = 'Off';}
		else if (status == 1) {description = 'Find RK Only'; RKNew = 1;}
		else if (status == 2) {description = 'On'; RKNew = 1;}
		else {Molpy.Notify('Display Description Error - RKAutoClick: ' + status, 1);}
	}
	else if (option == 'RefreshRate') {
		description = refreshRate;
	}
	else {
		Molpy.Notify(option + ' is not a valid option.', 1);
		error = 1;
	}

	if (error == 0) {g(option + 'Desc').innerHTML = '
' + description;}
}

//Beach Ball Startup
//Set Settings
if (Molpy.Got('Kitnip') == 1){RKAlertFrequency = 10;}

//Create Menu
$('#optionsItems').append('

BeachBall Settings

v ' + version + '

');
$('#optionsItems').append('

Redundakitty Auto Click

');
$('#optionsItems').append('

Logicat Auto Click

');
$('#optionsItems').append('

Ninja Auto Click

');
$('#optionsItems').append('

Ninja Visual Alert

');
$('#optionsItems').append('

Audio Alerts

');
$('#optionsItems').append('

Refresh Rate

');
//$('#optionsItems').append('

Spawn RK

');
//$('#optionsItems').append('

Extend RK

');
DisplayDescription('RKAutoClick', RKAutoClickStatus);
DisplayDescription('LCAutoClick', LCAutoClickStatus);
DisplayDescription('NinjaAutoClick', NinjaAutoClickStatus);
DisplayDescription('BorderAlert', BorderAlertStatus);
DisplayDescription('AudioAlerts', AudioAlertsStatus);
DisplayDescription('RefreshRate', refreshRate);

Molpy.Notify('BeachBall version ' + version + ' loaded for SandCastle Builder version ' + SCBversion, 1);
Loop();

function MainProgram() {
	Time_to_ONG = (Molpy.NPlength * 1000) - Molpy.ONGelapsed;
	RedundaKitty();
	Ninja();
	Loop();
}

function Loop() {
	setTimeout(MainProgram, refreshRate);
}
/*
function SpawnRK() {
	Molpy.redactedCountup = Molpy.redactedToggle - 1;
}

function ExtendRK() {
	Molpy.redactedCountup = 1;
}
*/
<|endoftext|>


<commit_before>

var Beardy = require('./Beardy');

var SIMPLE_TEMPLATE = 'abc def - zxc asqwezc { } [ ] ! # . $ *';

module.exports = [

	{ name: 'Instantiating', code: function () {
		var b = new Beardy;
		return b instanceof Beardy;
	}},

	{ name: 'Render without data', code: function () {
		var b = new Beardy;
		var thr = false;

		try
		{
			b.render();
		}
		catch (e)
		{
			thr = (e instanceof TypeError && e.message === 'Need data to render');
		}

		return thr;
	}},

	{ name: 'Render undefined template', code: function () {
		var b = new Beardy;
		var r = b.render({});
		return r === '';
	}},

	{ name: 'Render empty template', code: function () {
		var b = new Beardy('');
		var r = b.render({});
		return r === '';
	}},

	{ name: 'Render simple string', code: function () {
		var b = new Beardy(SIMPLE_TEMPLATE);
		var r = b.render({});
		return r === SIMPLE_TEMPLATE;
	}},

	{ name: 'In-place rendering', code: function () {
		return Beardy(SIMPLE_TEMPLATE, {1:1}) === SIMPLE_TEMPLATE;
	}},

	{ name: 'Commentary', code: function () {
		return (
		    Beardy('{# asd qwe zxc #}', {}) === ''
		 && Beardy('asd{# qwe #}zxc', {}) === 'asdzxc'
		 && Beardy('asd{# {} { # } {{ }} \n \n \t {% %} #}zxc', {}) === 'asdzxc'
		);
	}},

	{ name: 'Simple substs', code: function () {
		return Beardy('{{ a }}-{{ b }}-{{ 15 }}{# -{{ d }} #}', { a: 5, b: 7, '15': 10, d: 'abc' }) === '5-7-10';
	}},

	/*
		undefined and null means empty string,
		empty list uses toString strategy, so it means empty string as well
	 */
	{ name: 'Type coercion of empty objects', code: function () {
		return Beardy('{{ A }}{{ B }}{{ C }}{{ D }}', { A: undefined, B: null, C: '', D: [] }) === '';
	}},

	/*
		as common, toString strategy is used,
		this is mostly similar to JS native behavior
	 */
	{ name: 'Type coercion of non empty primitives and objects', code: function () {
		return Beardy('{{OBJECT}},{{TRUE}},{{FALSE}},{{NUMBER}},{{ARRAY}},{{INF}},{{NAN}}', {
			OBJECT : {},
			TRUE   : true,
			FALSE  : false,
			NUMBER : 7,
			ARRAY  : [1,2,3],
			INF    : 1/0,
			NAN    : 1 * 'a'
		}) === '[object Object],true,false,7,1,2,3,Infinity,NaN';
	}},

	/*
		outer space trimmed,
		inner spaces saved
	 */
	{ name: 'Space in substs', code: function () {
		return Beardy('{{   a b  c    }}', { 'a b  c': true }) === 'true';
	}},

	/*
		Function takes one special arguments: name of subst it used as
	 */
	{ name: 'Function values in substs', code: function () {
		return (
		    Beardy('{{ fn }}', { x: 5, fn: function () { return this.x * this.x; } }) === '25'
		 && Beardy('{{ fn }}', { x: 5, fn: function () { return '3' + this.x; } }) === '35'
		 && Beardy('{{ fn }}', { x: 5, fn: function (name) { return name; } }) === 'fn'
		);
	}},

	{ name: 'Simple blocks', code: function () {
		return Beardy(
			'<{% x %}1{% . %}><{% y %}2{% . %}><{% z %}3{% . %}>',
			{ x:null, y:'5', z:[1,2,3]})
			=== '<><2><333>';
	}},

	{ name: 'Falsy blocks', code: function () {
		return (
		    Beardy('{% B %}Block{% . %}', {}) === ''
		 && Beardy('{% B %}Block{% . %}', {1: 1}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: undefined}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: null}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: false}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: ''}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: 0}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: []}) === ''
		);
	}},

	{ name: 'Single-run blocks', code: function () {
		return (
		    Beardy('{% B %}Block{% . %}', {B: 1}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: true}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: ' '}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: {}}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [1]}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [true]}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [' ']}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [{}]}) === 'Block'
		);
	}},

	{ name: 'Function values in blocks', code: function () {
		return (
		    Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: function () { return; } }) === ''
		 && Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: Array }) === 'B_'
		 && Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: function () { return this.x; } }) === 'B_'
		 && Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: function () { return this.x.split(','); } }) === 'B_B_B_'
		);
	}},

	/*
		{{ * }}      - item
		{{ # }}      - 0-based index     (0, 1, 2, ..., L-2, L-1)
		{{ #0 }}     - 0-based index
		{{ #1 }}     - 1-based index    (1, 2, 3, ..., L-1, L)
		{{ #- }}     - negative 1-based index from end (-L, 1-L, 2-L, ..., -2, -1)
		{{ #first }} - first element (bool)
		{{ #last }}  - last element (bool)
	 */
	{ name: 'Block context special keys', code: function () {
		return Beardy(
			'[{% B %}<{{ #first }}={{ * }}={{ # }}={{ #0 }}={{ #1 }}={{ #- }}={{ #last }}>{% . %}]',
			{ B: ['a', 'b', 'c', 'd'] })
			=== '[<true=a=0=0=1=-4=false><false=b=1=1=2=-3=false><false=c=2=2=3=-2=false><false=d=3=3=4=-1=true>]';
	}},

	{ name: 'Global Block context item key', code: function () {
		return Beardy('{{ * }};{% * %}{{ * }}-{% . %}',
			[ 1, 2, 3 ]
		) === '1,2,3;1-2-3-';
	}},

	{ name: 'Block context key extending', code: function () {
		function mul () { return this.b * this['#-']; }
		return Beardy(
			'[{% B %}<{{ a }}={{ b }}={{ c }}={{ # }}>{% . %}]',
			{ B: [
				{ a: 2, b: 2, c: mul },
				{ a: 3, b: 2, c: mul },
				{ a: 4, b: 2, c: mul },
			] })
			=== '[<2=2=-6=0><3=2=-4=1><4=2=-2=2>]';
	}},

	{ name: 'Block context parenting', code: function () {
		return Beardy(
			'{{ X }}-{{ Y }}{% B %}:{{ X }}-{{ Y }}-{{ fn }}{% . %}',
			{
				X: 3,
				B: [
					{ Y: 3 },
					{ X: 4, Y: 5 }
				],
				fn: function () { return this.X; }
			})
			=== '3-:3-3-3:4-5-4';
	}},

	{ name: 'Block context key overriding', code: function () {
		return Beardy(
			'{% B %}{{ * }}-{{ # }}-{{ #last }}{% . %}',
			{
				B:
				[
					{ '*': 1, '#': 2, '#last': function () { return 3; } }
				]
			})
			=== '1-2-3';
	}},

	{ name: 'Nested blocks-lists', code: function () {
		return Beardy(
			'{% B %}{% * %}{{ * }}, {% . %};{% . %}',
			{ B: [[], [1], [1,2,3]] })
			=== ';1, ;1, 2, 3, ;';
	}},

	{ name: 'Nested blocks-structs', code: function () {
		return Beardy(
			'{% B %}{% A %}{{ * }}, {% . %};{% . %}',
			{ B: [{A:[1]}, {A:[2,3]}, {A:[4,5,6]}] })
			=== '1, ;2, 3, ;4, 5, 6, ;';
	}},

	{ name: 'Nested blocks-functions', code: function () {
		function stub () { return [1,2,3]; }
		function val () { return this.x; }
		return Beardy(
			'{% B %}{% * %}{{ * }}, {% . %};{% . %}',
			{ B: [stub, {x:[4,5], '*': val}, [6,7,8]] })
			=== '1, 2, 3, ;4, 5, ;6, 7, 8, ;';
	}},

	{ name: 'Nested blocks parenting', code: function () {
		function val () { return '' + this.A + this.B; }
		return Beardy('{{ A }}{{ B }}{{ C }},{% B1 %}'+
			'{{ A }}{{ B }}{{ C }},'+
			'{% B2 %}{{ A }}{{ B }}{{ C }},'+
			'{% B3 %}{{ A }}{{ B }}{{ C }}{% . %}{% . %}{% . %}',
			{
				A: 3,
				B1:
				{
					B: 4,
					B2:
					{
						C: val,
						B3: {}
					}
				}
			}) === '3,34,3434,3434';
	}},

	{ name: 'Nested blocks overriding', code: function () {
		function val () { return '' + this.A + this.B; }
		function no () { return ''; }
		return Beardy('{{ A }}{{ B }}{{ C }},{% B1 %}'+
			'{{ A }}{{ B }}{{ C }},'+
			'{% B2 %}{{ A }}{{ B }}{{ C }},'+
			'{% B3 %}{{ A }}{{ B }}{{ C }}{% . %}{% . %}{% . %}',
			{
				A: 3,
				B1:
				{
					A: 5,
					B: 4,
					B2:
					{
						A: 6,
						B: 5,
						C: val,
						B3:
						{
							A: 7,
							B: 6,
							C: no
						}
					}
				}
			}) === '3,54,6565,76';
	}},

	{ name: 'Dot access', code: function () {
		return Beardy('{{ A.B.C }},{{ B.1.0 }},{{ C.D.E }}',
			{
				A: { B: { C: 'a' }},
				B: [ 0, [ 'b' ] ],
				C: function () { return { D: function () { return { E: function () { return 'c' }, E1: 1 }; } }; }
			}) === 'a,b,c';
	}},

	{ name: 'Dot access shorting', code: function () {
		return Beardy('{{ A.B.C }}-{% A %}{{ B.C }}-{% B %}{{ C }}-{% C %}{{ * }}{% . %}{% . %}{% . %}',
			{ A: { B: { C: 5 } } }) === '5-5-5-5';
	}},

	{ name: 'Filter signature', code: function () {
		var b = new Beardy('{{ X:F(1,2,3) }}');
		var d = { X: 1 };

		b.filters =
		{
			F: function (value, args, key, data) { return '' +
				(this === b) + ';' +
				value + ';' +
				args + ';' +
				key + ';' +
				(data['*'] === d); }
		};
		var x = b.render(d);
		return x === 'true;1;1,2,3;X;true';
	}},

	{ name: 'Filter:default', code: function () {
		return Beardy('{{ X:default(1) }},{{ Y:default(2) }}', { X: 3 }) === '3,2';
	}},

	{ name: 'Filter:not', code: function () {
		return Beardy('{% C %}{{ A:not }},{% . %}',
		{
			C:
			[
				{},
				{ A: true },
				{ A: false },
				{ A: 1 },
				{ A: 0 },
				{ A: {} },
				{ A: [] },
				{ A: [1] },
			]
		}) === 'true,false,true,false,true,false,false,false,';
	}},

	{ name: 'Filter:bool', code: function () {
		return Beardy('{% C %}{{ A:bool }},{% . %}',
		{
			C:
			[
				{},
				{ A: true },
				{ A: false },
				{ A: 1 },
				{ A: 0 },
				{ A: {} },
				{ A: [] },
				{ A: [1] },
			]
		}) === 'false,true,false,true,false,true,true,true,';
	}},

	{ name: 'Filter:empty', code: function () {
		return Beardy('{{ A:empty }},{{ B:empty }},{{ C:empty }},{{ D:empty }}',
		{
			A: true,
			B: 1,
			C: [1],
			D: []
		}) === 'false,false,false,true';
	}},

	//{ name: 'Filter:', code: function () {

];
<commit_msg>Update test Dot access.<commit_after>

var Beardy = require('./Beardy');

var SIMPLE_TEMPLATE = 'abc def - zxc asqwezc { } [ ] ! # . $ *';

module.exports = [

	{ name: 'Instantiating', code: function () {
		var b = new Beardy;
		return b instanceof Beardy;
	}},

	{ name: 'Render without data', code: function () {
		var b = new Beardy;
		var thr = false;

		try
		{
			b.render();
		}
		catch (e)
		{
			thr = (e instanceof TypeError && e.message === 'Need data to render');
		}

		return thr;
	}},

	{ name: 'Render undefined template', code: function () {
		var b = new Beardy;
		var r = b.render({});
		return r === '';
	}},

	{ name: 'Render empty template', code: function () {
		var b = new Beardy('');
		var r = b.render({});
		return r === '';
	}},

	{ name: 'Render simple string', code: function () {
		var b = new Beardy(SIMPLE_TEMPLATE);
		var r = b.render({});
		return r === SIMPLE_TEMPLATE;
	}},

	{ name: 'In-place rendering', code: function () {
		return Beardy(SIMPLE_TEMPLATE, {1:1}) === SIMPLE_TEMPLATE;
	}},

	{ name: 'Commentary', code: function () {
		return (
		    Beardy('{# asd qwe zxc #}', {}) === ''
		 && Beardy('asd{# qwe #}zxc', {}) === 'asdzxc'
		 && Beardy('asd{# {} { # } {{ }} \n \n \t {% %} #}zxc', {}) === 'asdzxc'
		);
	}},

	{ name: 'Simple substs', code: function () {
		return Beardy('{{ a }}-{{ b }}-{{ 15 }}{# -{{ d }} #}', { a: 5, b: 7, '15': 10, d: 'abc' }) === '5-7-10';
	}},

	/*
		undefined and null means empty string,
		empty list uses toString strategy, so it means empty string as well
	 */
	{ name: 'Type coercion of empty objects', code: function () {
		return Beardy('{{ A }}{{ B }}{{ C }}{{ D }}', { A: undefined, B: null, C: '', D: [] }) === '';
	}},

	/*
		as common, toString strategy is used,
		this is mostly similar to JS native behavior
	 */
	{ name: 'Type coercion of non empty primitives and objects', code: function () {
		return Beardy('{{OBJECT}},{{TRUE}},{{FALSE}},{{NUMBER}},{{ARRAY}},{{INF}},{{NAN}}', {
			OBJECT : {},
			TRUE   : true,
			FALSE  : false,
			NUMBER : 7,
			ARRAY  : [1,2,3],
			INF    : 1/0,
			NAN    : 1 * 'a'
		}) === '[object Object],true,false,7,1,2,3,Infinity,NaN';
	}},

	/*
		outer space trimmed,
		inner spaces saved
	 */
	{ name: 'Space in substs', code: function () {
		return Beardy('{{   a b  c    }}', { 'a b  c': true }) === 'true';
	}},

	/*
		Function takes one special arguments: name of subst it used as
	 */
	{ name: 'Function values in substs', code: function () {
		return (
		    Beardy('{{ fn }}', { x: 5, fn: function () { return this.x * this.x; } }) === '25'
		 && Beardy('{{ fn }}', { x: 5, fn: function () { return '3' + this.x; } }) === '35'
		 && Beardy('{{ fn }}', { x: 5, fn: function (name) { return name; } }) === 'fn'
		);
	}},

	{ name: 'Simple blocks', code: function () {
		return Beardy(
			'<{% x %}1{% . %}><{% y %}2{% . %}><{% z %}3{% . %}>',
			{ x:null, y:'5', z:[1,2,3]})
			=== '<><2><333>';
	}},

	{ name: 'Falsy blocks', code: function () {
		return (
		    Beardy('{% B %}Block{% . %}', {}) === ''
		 && Beardy('{% B %}Block{% . %}', {1: 1}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: undefined}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: null}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: false}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: ''}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: 0}) === ''
		 && Beardy('{% B %}Block{% . %}', {B: []}) === ''
		);
	}},

	{ name: 'Single-run blocks', code: function () {
		return (
		    Beardy('{% B %}Block{% . %}', {B: 1}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: true}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: ' '}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: {}}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [1]}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [true]}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [' ']}) === 'Block'
		 && Beardy('{% B %}Block{% . %}', {B: [{}]}) === 'Block'
		);
	}},

	{ name: 'Function values in blocks', code: function () {
		return (
		    Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: function () { return; } }) === ''
		 && Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: Array }) === 'B_'
		 && Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: function () { return this.x; } }) === 'B_'
		 && Beardy('{% B %}B_{% . %}', {x: 'a,b,c', B: function () { return this.x.split(','); } }) === 'B_B_B_'
		);
	}},

	/*
		{{ * }}      - item
		{{ # }}      - 0-based index     (0, 1, 2, ..., L-2, L-1)
		{{ #0 }}     - 0-based index
		{{ #1 }}     - 1-based index    (1, 2, 3, ..., L-1, L)
		{{ #- }}     - negative 1-based index from end (-L, 1-L, 2-L, ..., -2, -1)
		{{ #first }} - first element (bool)
		{{ #last }}  - last element (bool)
	 */
	{ name: 'Block context special keys', code: function () {
		return Beardy(
			'[{% B %}<{{ #first }}={{ * }}={{ # }}={{ #0 }}={{ #1 }}={{ #- }}={{ #last }}>{% . %}]',
			{ B: ['a', 'b', 'c', 'd'] })
			=== '[<true=a=0=0=1=-4=false><false=b=1=1=2=-3=false><false=c=2=2=3=-2=false><false=d=3=3=4=-1=true>]';
	}},

	{ name: 'Global Block context item key', code: function () {
		return Beardy('{{ * }};{% * %}{{ * }}-{% . %}',
			[ 1, 2, 3 ]
		) === '1,2,3;1-2-3-';
	}},

	{ name: 'Block context key extending', code: function () {
		function mul () { return this.b * this['#-']; }
		return Beardy(
			'[{% B %}<{{ a }}={{ b }}={{ c }}={{ # }}>{% . %}]',
			{ B: [
				{ a: 2, b: 2, c: mul },
				{ a: 3, b: 2, c: mul },
				{ a: 4, b: 2, c: mul },
			] })
			=== '[<2=2=-6=0><3=2=-4=1><4=2=-2=2>]';
	}},

	{ name: 'Block context parenting', code: function () {
		return Beardy(
			'{{ X }}-{{ Y }}{% B %}:{{ X }}-{{ Y }}-{{ fn }}{% . %}',
			{
				X: 3,
				B: [
					{ Y: 3 },
					{ X: 4, Y: 5 }
				],
				fn: function () { return this.X; }
			})
			=== '3-:3-3-3:4-5-4';
	}},

	{ name: 'Block context key overriding', code: function () {
		return Beardy(
			'{% B %}{{ * }}-{{ # }}-{{ #last }}{% . %}',
			{
				B:
				[
					{ '*': 1, '#': 2, '#last': function () { return 3; } }
				]
			})
			=== '1-2-3';
	}},

	{ name: 'Nested blocks-lists', code: function () {
		return Beardy(
			'{% B %}{% * %}{{ * }}, {% . %};{% . %}',
			{ B: [[], [1], [1,2,3]] })
			=== ';1, ;1, 2, 3, ;';
	}},

	{ name: 'Nested blocks-structs', code: function () {
		return Beardy(
			'{% B %}{% A %}{{ * }}, {% . %};{% . %}',
			{ B: [{A:[1]}, {A:[2,3]}, {A:[4,5,6]}] })
			=== '1, ;2, 3, ;4, 5, 6, ;';
	}},

	{ name: 'Nested blocks-functions', code: function () {
		function stub () { return [1,2,3]; }
		function val () { return this.x; }
		return Beardy(
			'{% B %}{% * %}{{ * }}, {% . %};{% . %}',
			{ B: [stub, {x:[4,5], '*': val}, [6,7,8]] })
			=== '1, 2, 3, ;4, 5, ;6, 7, 8, ;';
	}},

	{ name: 'Nested blocks parenting', code: function () {
		function val () { return '' + this.A + this.B; }
		return Beardy('{{ A }}{{ B }}{{ C }},{% B1 %}'+
			'{{ A }}{{ B }}{{ C }},'+
			'{% B2 %}{{ A }}{{ B }}{{ C }},'+
			'{% B3 %}{{ A }}{{ B }}{{ C }}{% . %}{% . %}{% . %}',
			{
				A: 3,
				B1:
				{
					B: 4,
					B2:
					{
						C: val,
						B3: {}
					}
				}
			}) === '3,34,3434,3434';
	}},

	{ name: 'Nested blocks overriding', code: function () {
		function val () { return '' + this.A + this.B; }
		function no () { return ''; }
		return Beardy('{{ A }}{{ B }}{{ C }},{% B1 %}'+
			'{{ A }}{{ B }}{{ C }},'+
			'{% B2 %}{{ A }}{{ B }}{{ C }},'+
			'{% B3 %}{{ A }}{{ B }}{{ C }}{% . %}{% . %}{% . %}',
			{
				A: 3,
				B1:
				{
					A: 5,
					B: 4,
					B2:
					{
						A: 6,
						B: 5,
						C: val,
						B3:
						{
							A: 7,
							B: 6,
							C: no
						}
					}
				}
			}) === '3,54,6565,76';
	}},

	{ name: 'Dot access', code: function () {
		return Beardy('{{ A.B.C }},{{ B.1.0 }},{{ C.D.E }},{{ A.B }},{{ C.D }},{{ *.A.B.C }},{{ A.E }},{{ *.D }}',
			{
				A: { B: { C: 'a' }},
				B: [ 0, [ 'b' ] ],
				C: function () { return { D: function () { return { E: function () { return 'c' }, E1: 1 }; } }; }
			}) === 'a,b,c,[object Object],[object Object],a,,';
	}},

	{ name: 'Dot access shorting', code: function () {
		return Beardy('{{ A.B.C }}-{% A %}{{ B.C }}-{% B %}{{ C }}-{% C %}{{ * }}{% . %}{% . %}{% . %}',
			{ A: { B: { C: 5 } } }) === '5-5-5-5';
	}},

	{ name: 'Filter signature', code: function () {
		var b = new Beardy('{{ X:F(1,2,3) }}');
		var d = { X: 1 };

		b.filters =
		{
			F: function (value, args, key, data) { return '' +
				(this === b) + ';' +
				value + ';' +
				args + ';' +
				key + ';' +
				(data['*'] === d); }
		};
		var x = b.render(d);
		return x === 'true;1;1,2,3;X;true';
	}},

	{ name: 'Filter:default', code: function () {
		return Beardy('{{ X:default(1) }},{{ Y:default(2) }}', { X: 3 }) === '3,2';
	}},

	{ name: 'Filter:not', code: function () {
		return Beardy('{% C %}{{ A:not }},{% . %}',
		{
			C:
			[
				{},
				{ A: true },
				{ A: false },
				{ A: 1 },
				{ A: 0 },
				{ A: {} },
				{ A: [] },
				{ A: [1] },
			]
		}) === 'true,false,true,false,true,false,false,false,';
	}},

	{ name: 'Filter:bool', code: function () {
		return Beardy('{% C %}{{ A:bool }},{% . %}',
		{
			C:
			[
				{},
				{ A: true },
				{ A: false },
				{ A: 1 },
				{ A: 0 },
				{ A: {} },
				{ A: [] },
				{ A: [1] },
			]
		}) === 'false,true,false,true,false,true,true,true,';
	}},

	{ name: 'Filter:empty', code: function () {
		return Beardy('{{ A:empty }},{{ B:empty }},{{ C:empty }},{{ D:empty }}',
		{
			A: true,
			B: 1,
			C: [1],
			D: []
		}) === 'false,false,false,true';
	}},

	//{ name: 'Filter:', code: function () {

];
<|endoftext|>


<commit_before>Meteor.methods({
  /**
   * @summary Handles Contact form submission
   * @method
   *   @param {string} name
   *   @param {string} email
   *   @param {string} comments
   */
  submitContactForm(name, email, comments) {
    check(name, String);
    check(email, String);
    check(comments, String);

    this.unblock();

    Email.send({
      to: 'micah.henning@wcasa.org',
      from: `${name} <${email}>`,
      subject: 'Comments from Website',
      text: `${name} has submitted comments on the WCASA website:\r\n\r\n${comments}`,
    });
  },
});
<commit_msg>Resolved email permissions oversight.<commit_after>Meteor.methods({
  /**
   * @summary Handles Contact form submission
   * @method
   *   @param {string} name
   *   @param {string} email
   *   @param {string} comments
   */
  submitContactForm(name, email, comments) {
    check(name, String);
    check(email, String);
    check(comments, String);

    this.unblock();

    Email.send({
      to: 'wcasa@wcasa.org',
      from: 'WCASA Website <website@wcasa.org>',
      replyTo: `${name} <${email}>`,
      subject: `Message from ${name}`,
      text: `${name} (${email}) has submitted a message through the contact form on the WCASA website:\r\n\r\n${comments}`,
    });
  },
});
<|endoftext|>


<commit_before>var gulp = require("gulp");
var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");
var watchify = require("watchify");
var gutil = require("gulp-util");
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var buffer = require('vinyl-buffer');

var destination = '../../public/compiled/';

var build = browserify({
    standalone: 'LichessChat',
    basedir: '.',
    debug: true,
    entries: ['src/main.ts'],
    cache: {},
    packageCache: {}
  })
  .plugin(tsify);
  // .transform('babelify', {
  //   presets: ['es2015'],
  //   extensions: ['.ts']
  // });

var watchedBrowserify = watchify(build);

function bundle() {
  return watchedBrowserify
    .bundle()
    .pipe(source('lichess.chat2.js'))
    .pipe(buffer())
    .pipe(sourcemaps.init({
      loadMaps: true
    }))
    .on('error', function(error) { gutil.log(gutil.colors.red(error.message)); })
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest(destination));
}

gulp.task("default", [], bundle);
// watchedBrowserify.on("update", bundle);
// watchedBrowserify.on("log", gutil.log);

gulp.task("prod", [], function() {
  return build
    .bundle()
    .pipe(source('lichess.chat2.min.js'))
    .pipe(buffer())
    // .pipe(sourcemaps.init({loadMaps: false}))
    .pipe(uglify())
    .pipe(sourcemaps.write('./'))
    .pipe(gulp.dest(destination));
});
<commit_msg>chat2: unfuck the JS build thanks to @veloce<commit_after>var gulp = require("gulp");
var browserify = require("browserify");
var source = require('vinyl-source-stream');
var tsify = require("tsify");
var watchify = require("watchify");
var gutil = require("gulp-util");
var uglify = require('gulp-uglify');
var buffer = require('vinyl-buffer');

var destination = '../../public/compiled/';

function build(debug) {
  return browserify('src/main.ts', {
      standalone: 'LichessChat',
      debug: debug
    })
    .plugin(tsify);
}

var watchedBrowserify = watchify(build(true));

function bundle() {
  return watchedBrowserify
    .bundle()
    .on('error', function(error) {
      gutil.log(gutil.colors.red(error.message));
    })
    .pipe(source('lichess.chat2.js'))
    .pipe(buffer())
    .pipe(gulp.dest(destination));
}

gulp.task("default", [], bundle);
watchedBrowserify.on("update", bundle);
watchedBrowserify.on("log", gutil.log);

gulp.task("prod", [], function() {
  return build(false)
    .bundle()
    .pipe(source('lichess.chat2.min.js'))
    .pipe(buffer())
    .pipe(uglify())
    .pipe(gulp.dest(destination));
});
<|endoftext|>