<commit_before>cedeg = (function ()
{
var instance;

function record_widget (Width, Heigth)
{
    Gwt.Gui.HBox.call (this, 0);
    this.SetSize (Width, Heigth);
    this.SetClassName ("record_widget");

    this.code = new Gwt.Gui.Entry ("Código");
    this.code.SetExpand (false);
    this.code.SetWidth (120);
    this.name = new Gwt.Gui.StaticText ("Nombre");
    this.name.SetExpand (false);
    this.name.SetWidth (this.GetWidth() - 480);
    this.name.SetValign (Gwt.Gui.Contrib.Valign.Middle);
    this.partial = new Gwt.Gui.Entry ("Parcial");
    this.partial.SetExpand (false);
    this.partial.SetWidth (120);
    this.partial.ChangeToMonetary();
    this.debit = new Gwt.Gui.Entry ("Debe");
    this.debit.SetExpand (false);
    this.debit.SetWidth (120);
    this.debit.ChangeToMonetary();
    this.credit = new Gwt.Gui.Entry ("Haber");
    this.credit.SetExpand (false);
    this.credit.SetWidth (120);
    this.credit.ChangeToMonetary();

    this.Add (this.code);
    this.Add (this.name);
    this.Add (this.partial);
    this.Add (this.debit);
    this.Add (this.credit);

    this.code.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.check_code.bind(this));
}

record_widget.prototype = new Gwt.Gui.HBox ();
record_widget.prototype.constructor = record_widget;

record_widget.prototype._record_widget = function ()
{
    this.code._Entry();
    this.name._StaticText();
    this.partial._Entry();
    this.debit._Entry();
    this.credit._Entry();

    this.code = null;
    this.name = null;
    this.partial = null;
    this.debit = null;
    this.credit = null;
}

record_widget.prototype.Reset = function ()
{
    this.code.Reset ();
    this.name.SetText ("Nombre");
    this.partial.Reset ();
    this.debit.Reset ();
    this.credit.Reset ();
}

record_widget.prototype.check_code = function (event)
{
    if(event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        var Query = 'SELECT "Name" FROM "AccountingAccount" WHERE "Code"=\'{0}\' LIMIT 1'.replace("{0}", this.code.GetText());
        new Gwt.Core.SqlQuery (Query, this.autocomplete.bind(this));
    }
}

record_widget.prototype.autocomplete = function (Res)
{
    console.log (Res);
    if (Res.Data.length === 1)
    {
        this.name.SetText (Res.Data[0].Name);
    }
    else
    {
        this.name.SetText ("Nombre");
    }
}

function cedeg()
{
    Gwt.Gui.Window.call (this, "Comprobante De Egreso");

    this.SetSize (840, 460);
    this.SetPosition (Gwt.Gui.WIN_POS_CENTER);
    this.SetBorderSpacing (12);

    this.EnableMenu ();
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.cabinet.in.svg", "Guardar", this.Guardar.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.delete.svg", "Eliminar", this.Eliminar.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.power.svg", "Salir", function(){window.cedeg.close(); window.gcontrol.open();}, Gwt.Gui.MENU_QUIT_APP);

    this.layout = new Gwt.Gui.VBox ();
    this.SetLayout (this.layout);

    this.slider = new Gwt.Gui.Slider (3);
    this.slider.SetSize (this.layout.GetWidth (), this.layout.GetHeight ());
    this.slider.Setup ();

    this.number = new Gwt.Gui.Entry ("Número");
    this.place = new Gwt.Gui.Entry ("Lugar");
    this.date = new Gwt.Gui.Date ("Creación");
    this.date.Now ();
    this.holder = new Gwt.Gui.Entry ("A Favor De");
    this.amount = new Gwt.Gui.Entry ("Valor");
    this.amount.ChangeToMonetary();
    this.bank = new Gwt.Gui.Entry ("Banco");
    this.check = new Gwt.Gui.Entry ("Cheque");
    this.checking_account = new Gwt.Gui.Entry ("Cuenta");
    this.concept = new Gwt.Gui.Text ("Concepto");
    this.records = [];
    this.update = false;
    this.Report = null;

    this.layout.Add (this.slider);

    for (var i = 0; i < 20; i++)
    {
        this.records[i] = new record_widget (this.slider.GetWidth (), 24);
    }

    this.slider.AddSlotWidget (0, this.number);
    this.slider.AddSlotWidget (0, this.place);
    this.slider.AddSlotWidget (0, this.date);
    this.slider.AddSlotWidget (0, this.holder);
    this.slider.AddSlotWidget (0, this.amount);
    this.slider.AddSlotWidget (0, this.bank);
    this.slider.AddSlotWidget (0, this.check);
    this.slider.AddSlotWidget (0, this.checking_account);
    this.slider.AddSlotWidget (0, this.concept);

    for (var i=0; i<this.records.length; i++)
    {
        if (i<=9)
        {
            this.slider.AddSlotWidget (1, this.records[i]);
        }
        else
        {
            this.slider.AddSlotWidget (2, this.records[i]);
        }
    }

    this.number.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.CheckNumber.bind(this));

}

cedeg.prototype = new Gwt.Gui.Window ();
cedeg.prototype.constructor = cedeg;

cedeg.prototype._App = function ()
{
    this.number._Entry ();
    this.place._Entry ();
    this.date._Date ();
    this.holder._Entry ();
    this.amount._Entry ();
    this.bank._Entry ();
    this.check._Entry ();
    this.checking_account._Entry ();
    this.concept._Text ();
    this.slider._Slider ();
    this.Report === null ? 0 : this.Report.close ();

    this.number = null;
    this.place = null;
    this.date = null;
    this.holder = null;
    this.amount = null;
    this.bank = null;
    this.check = null;
    this.checking_account = null;
    this.concept = null;
    this.slider = null;

    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i]._record_widget();
        this.records[i] = null;
    }
    this.records = null;

    this.layout._VBox ();
    this.layout = null;
    this.Report = null;
};

cedeg.prototype.Guardar = function ()
{
    var Records = [];
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Records.push({
                "Code": this.records[i].code.GetText (),
                "Name": this.records[i].name.GetText (),
                "Partial": this.records[i].partial.GetText (),
                "Debit": this.records[i].debit.GetText (),
                "Credit": this.records[i].credit.GetText()
            });
        }
    }

    var Data = [
        {
            "Number": this.number.GetText (),
            "Place": this.place.GetText (),
            "Date": this.date.GetText (),
            "Holder": this.holder.GetText (),
            "Amount": this.amount.GetText (),
            "Bank": this.bank.GetText (),
            "Check": this.check.GetText (),
            "CheckingAccount": this.checking_account.GetText (),
            "Concept": this.concept.GetText (),
            "Records": Records
        }
    ];

    new Gwt.Core.Request("/backend/cedeg/save/", this.SaveResponse.bind (this), [new Gwt.Core.Parameter(Gwt.Core.PARAM_TYPE_JSON, "Params", Data)]);
};

cedeg.prototype.Eliminar = function ()
{

};

cedeg.prototype.Reset = function ()
{
    this.number.SetText ("");
    this.place.SetText ("");
    this.date.Now ();
    this.holder.SetText ("");
    this.amount.SetText ("");
    this.bank.SetText ("");
    this.check.SetText ("");
    this.checking_account.SetText ("");
    this.concept.SetText ("");

    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i].Reset ();
    }
};

cedeg.prototype.CheckNumber = function (Event)
{
    if(Event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        if (this.number.GetText () === "")
        {
            var Query = "SELECT \"Number\" FROM \"AccountingDisbVou\" ORDER BY \"Number\" DESC LIMIT 1";
            new Gwt.Core.SqlQuery(Query, this.NextNumber.bind(this));
        }
    }
};

cedeg.prototype.NextNumber = function (Res)
{
    this.number.SetText(Number(Res.Data[0].Number)+1);
};

cedeg.prototype.SaveResponse = function (Res)
{
    if (Res.Result === 1)
    {
        this.Report = Gwt.Core.Contrib.LoadDocument ("/share/documents/cedeg.html");
        this.Report.addEventListener ("load", this.ReportLoad.bind (this));
    }
};

cedeg.prototype.ReportLoad = function ()
{
    var doc = this.Report.contentWindow.document;
    doc.getElementById ("Number").textContent = this.number.GetText();
    doc.getElementById ("Place").textContent = this.place.GetText()+", "+this.date.GetText ();
    doc.getElementById ("Holder").textContent = this.holder.GetText ();
    doc.getElementById ("AmountHuman").textContent = Gwt.Core.Contrib.NumberToHumanReadable (this.amount.GetText())+"PESOS MTE";
    doc.getElementById ("Bank").textContent = this.bank.GetText ();
    doc.getElementById ("Check").textContent = this.check.GetText ();
    doc.getElementById ("CheckingAccount").textContent = this.checking_account.GetText ();
    doc.getElementById ("Concept").textContent = this.concept.GetText ();
    doc.getElementById ("Amount").textContent = this.amount.GetText ();

    var Records = [];
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Records.push({
                "Code": this.records[i].code.GetText (),
                "Name": this.records[i].name.GetText (),
                "Partial": this.records[i].partial.GetText (),
                "Debit": this.records[i].debit.GetText (),
                "Credit": this.records[i].credit.GetText()
            });
        }
    }

    for (var i=0; i < Records.length; i++)
    {
        doc.getElementById ("Code"+i).textContent = Records[i].Code;
        doc.getElementById ("Name"+i).textContent = Records[i].Name;
        doc.getElementById ("Partial"+i).textContent = Records[i].Partial;
        doc.getElementById ("Debit"+i).textContent = Records[i].Debit;
        doc.getElementById ("Credit"+i).textContent = Records[i].Credit;
    }

    for (i; i < this.records.length; i++)
    {
        doc.getElementById ("Code"+i).textContent = "";
        doc.getElementById ("Name"+i).textContent = "";
        doc.getElementById ("Partial"+i).textContent = "";
        doc.getElementById ("Debit"+i).textContent = "";
        doc.getElementById ("Credit"+i).textContent = "";
    }

    doc = undefined;
    this.Report = null;
    this.Reset ();
};

return new function ()
{
    this.open = function()
    {
        if(instance === undefined)
        {
            instance = new cedeg();
            instance.Open ();
            Gwt.Core.Contrib.SetActiveApp (window.cedeg);
        }
        else
        {
            console.log ("%app yet opened".replace("%app", instance.__proto__.constructor.name));
        }
    }

    this.close = function ()
    {
        if(instance !== undefined)
        {
            instance.Close();
            instance = undefined;
            Gwt.Core.Contrib.RemoveActiveApp ();
        }
    }
}
})();
<commit_msg>update<commit_after>cedeg = (function ()
{
var instance;

function record_widget (Width, Heigth)
{
    Gwt.Gui.HBox.call (this, 0);
    this.SetSize (Width, Heigth);
    this.SetClassName ("record_widget");

    this.code = new Gwt.Gui.Entry ("Código");
    this.code.SetExpand (false);
    this.code.SetWidth (120);
    this.name = new Gwt.Gui.StaticText ("Nombre");
    this.name.SetExpand (false);
    this.name.SetWidth (this.GetWidth() - 480);
    this.name.SetValign (Gwt.Gui.Contrib.Valign.Middle);
    this.partial = new Gwt.Gui.Entry ("Parcial");
    this.partial.SetExpand (false);
    this.partial.SetWidth (120);
    this.partial.ChangeToMonetary();
    this.debit = new Gwt.Gui.Entry ("Debe");
    this.debit.SetExpand (false);
    this.debit.SetWidth (120);
    this.debit.ChangeToMonetary();
    this.credit = new Gwt.Gui.Entry ("Haber");
    this.credit.SetExpand (false);
    this.credit.SetWidth (120);
    this.credit.ChangeToMonetary();

    this.Add (this.code);
    this.Add (this.name);
    this.Add (this.partial);
    this.Add (this.debit);
    this.Add (this.credit);

    this.code.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.check_code.bind(this));
}

record_widget.prototype = new Gwt.Gui.HBox ();
record_widget.prototype.constructor = record_widget;

record_widget.prototype._record_widget = function ()
{
    this.code._Entry();
    this.name._StaticText();
    this.partial._Entry();
    this.debit._Entry();
    this.credit._Entry();

    this.code = null;
    this.name = null;
    this.partial = null;
    this.debit = null;
    this.credit = null;
}

record_widget.prototype.Reset = function ()
{
    this.code.Reset ();
    this.name.SetText ("Nombre");
    this.partial.Reset ();
    this.debit.Reset ();
    this.credit.Reset ();
}

record_widget.prototype.check_code = function (event)
{
    if(event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        var Query = "SELECT \"Name\" FROM \"AccountingAccount\" WHERE \"Code\"='{0}' LIMIT 1".replace("{0}", this.code.GetText());
        new Gwt.Core.SqlQuery (Query, this.autocomplete.bind(this));
    }
}

record_widget.prototype.autocomplete = function (Res)
{
    console.log (Res);
    if (Res.Data.length === 1)
    {
        this.name.SetText (Res.Data[0].Name);
    }
    else
    {
        this.name.SetText ("Nombre");
    }
}

function cedeg()
{
    Gwt.Gui.Window.call (this, "Comprobante De Egreso");

    this.SetSize (840, 460);
    this.SetPosition (Gwt.Gui.WIN_POS_CENTER);
    this.SetBorderSpacing (12);

    this.EnableMenu ();
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.cabinet.in.svg", "Guardar", this.Guardar.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.delete.svg", "Eliminar", this.Eliminar.bind(this));
    this.AddMenuItem (Gwt.Core.Contrib.Images + "appbar.power.svg", "Salir", function(){window.cedeg.close(); window.gcontrol.open();}, Gwt.Gui.MENU_QUIT_APP);

    this.layout = new Gwt.Gui.VBox ();
    this.SetLayout (this.layout);

    this.slider = new Gwt.Gui.Slider (3);
    this.slider.SetSize (this.layout.GetWidth (), this.layout.GetHeight ());
    this.slider.Setup ();

    this.number = new Gwt.Gui.Entry ("Número");
    this.place = new Gwt.Gui.Entry ("Lugar");
    this.date = new Gwt.Gui.Date ("Creación");
    this.date.Now ();
    this.holder = new Gwt.Gui.Entry ("A Favor De");
    this.amount = new Gwt.Gui.Entry ("Valor");
    this.amount.ChangeToMonetary();
    this.bank = new Gwt.Gui.Entry ("Banco");
    this.check = new Gwt.Gui.Entry ("Cheque");
    this.checking_account = new Gwt.Gui.Entry ("Cuenta");
    this.concept = new Gwt.Gui.Text ("Concepto");
    this.records = [];
    this.update = false;
    this.Report = null;

    this.layout.Add (this.slider);

    for (var i = 0; i < 20; i++)
    {
        this.records[i] = new record_widget (this.slider.GetWidth (), 24);
    }

    this.slider.AddSlotWidget (0, this.number);
    this.slider.AddSlotWidget (0, this.place);
    this.slider.AddSlotWidget (0, this.date);
    this.slider.AddSlotWidget (0, this.holder);
    this.slider.AddSlotWidget (0, this.amount);
    this.slider.AddSlotWidget (0, this.bank);
    this.slider.AddSlotWidget (0, this.check);
    this.slider.AddSlotWidget (0, this.checking_account);
    this.slider.AddSlotWidget (0, this.concept);

    for (var i=0; i<this.records.length; i++)
    {
        if (i<=9)
        {
            this.slider.AddSlotWidget (1, this.records[i]);
        }
        else
        {
            this.slider.AddSlotWidget (2, this.records[i]);
        }
    }

    this.number.AddEvent (Gwt.Gui.Event.Keyboard.KeyPress, this.CheckNumber.bind(this));

}

cedeg.prototype = new Gwt.Gui.Window ();
cedeg.prototype.constructor = cedeg;

cedeg.prototype._App = function ()
{
    this.number._Entry ();
    this.place._Entry ();
    this.date._Date ();
    this.holder._Entry ();
    this.amount._Entry ();
    this.bank._Entry ();
    this.check._Entry ();
    this.checking_account._Entry ();
    this.concept._Text ();
    this.slider._Slider ();
    this.Report === null ? 0 : this.Report.close ();

    this.number = null;
    this.place = null;
    this.date = null;
    this.holder = null;
    this.amount = null;
    this.bank = null;
    this.check = null;
    this.checking_account = null;
    this.concept = null;
    this.slider = null;

    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i]._record_widget();
        this.records[i] = null;
    }
    this.records = null;

    this.layout._VBox ();
    this.layout = null;
    this.Report = null;
};

cedeg.prototype.Guardar = function ()
{
    var Records = [];
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Records.push({
                "Code": this.records[i].code.GetText (),
                "Name": this.records[i].name.GetText (),
                "Partial": this.records[i].partial.GetText (),
                "Debit": this.records[i].debit.GetText (),
                "Credit": this.records[i].credit.GetText()
            });
        }
    }

    var Data = [
        {
            "Number": this.number.GetText (),
            "Place": this.place.GetText (),
            "Date": this.date.GetText (),
            "Holder": this.holder.GetText (),
            "Amount": this.amount.GetText (),
            "Bank": this.bank.GetText (),
            "Check": this.check.GetText (),
            "CheckingAccount": this.checking_account.GetText (),
            "Concept": this.concept.GetText (),
            "Records": Records
        }
    ];

    new Gwt.Core.Request("/backend/cedeg/save/", this.SaveResponse.bind (this), [new Gwt.Core.Parameter(Gwt.Core.PARAM_TYPE_JSON, "Params", Data)]);
};

cedeg.prototype.Eliminar = function ()
{

};

cedeg.prototype.Reset = function ()
{
    this.number.SetText ("");
    this.place.SetText ("");
    this.date.Now ();
    this.holder.SetText ("");
    this.amount.SetText ("");
    this.bank.SetText ("");
    this.check.SetText ("");
    this.checking_account.SetText ("");
    this.concept.SetText ("");

    for(var i = 0; i < this.records.length; i++)
    {
        this.records[i].Reset ();
    }
};

cedeg.prototype.CheckNumber = function (Event)
{
    if(Event.keyCode === Gwt.Gui.Event.Keyboard.KeyCodes.Enter)
    {
        if (this.number.GetText () === "")
        {
            var Query = "SELECT \"Number\" FROM \"AccountingDisbVou\" ORDER BY \"Number\" DESC LIMIT 1";
            new Gwt.Core.SqlQuery(Query, this.NextNumber.bind(this));
        }
    }
};

cedeg.prototype.NextNumber = function (Res)
{
    this.number.SetText(Number(Res.Data[0].Number)+1);
};

cedeg.prototype.SaveResponse = function (Res)
{
    if (Res.Result === 1)
    {
        this.Report = Gwt.Core.Contrib.LoadDocument ("/share/documents/cedeg.html");
        this.Report.addEventListener ("load", this.ReportLoad.bind (this));
    }
};

cedeg.prototype.ReportLoad = function ()
{
    var doc = this.Report.contentWindow.document;
    doc.getElementById ("Number").textContent = this.number.GetText();
    doc.getElementById ("Place").textContent = this.place.GetText()+", "+this.date.GetText ();
    doc.getElementById ("Holder").textContent = this.holder.GetText ();
    doc.getElementById ("AmountHuman").textContent = Gwt.Core.Contrib.NumberToHumanReadable (this.amount.GetText())+"PESOS MTE";
    doc.getElementById ("Bank").textContent = this.bank.GetText ();
    doc.getElementById ("Check").textContent = this.check.GetText ();
    doc.getElementById ("CheckingAccount").textContent = this.checking_account.GetText ();
    doc.getElementById ("Concept").textContent = this.concept.GetText ();
    doc.getElementById ("Amount").textContent = this.amount.GetText ();

    var Records = [];
    for (var i=0; i < this.records.length; i++)
    {
        if (this.records[i].code.GetText() !== "")
        {
            Records.push({
                "Code": this.records[i].code.GetText (),
                "Name": this.records[i].name.GetText (),
                "Partial": this.records[i].partial.GetText (),
                "Debit": this.records[i].debit.GetText (),
                "Credit": this.records[i].credit.GetText()
            });
        }
    }

    for (var i=0; i < Records.length; i++)
    {
        doc.getElementById ("Code"+i).textContent = Records[i].Code;
        doc.getElementById ("Name"+i).textContent = Records[i].Name;
        doc.getElementById ("Partial"+i).textContent = Records[i].Partial;
        doc.getElementById ("Debit"+i).textContent = Records[i].Debit;
        doc.getElementById ("Credit"+i).textContent = Records[i].Credit;
    }

    for (i; i < this.records.length; i++)
    {
        doc.getElementById ("Code"+i).textContent = "";
        doc.getElementById ("Name"+i).textContent = "";
        doc.getElementById ("Partial"+i).textContent = "";
        doc.getElementById ("Debit"+i).textContent = "";
        doc.getElementById ("Credit"+i).textContent = "";
    }

    doc = undefined;
    this.Report = null;
    this.Reset ();
};

return new function ()
{
    this.open = function()
    {
        if(instance === undefined)
        {
            instance = new cedeg();
            instance.Open ();
            Gwt.Core.Contrib.SetActiveApp (window.cedeg);
        }
        else
        {
            console.log ("%app yet opened".replace("%app", instance.__proto__.constructor.name));
        }
    }

    this.close = function ()
    {
        if(instance !== undefined)
        {
            instance.Close();
            instance = undefined;
            Gwt.Core.Contrib.RemoveActiveApp ();
        }
    }
}
})();
<|endoftext|>


<commit_before>
/* Contains code for generating mountain levels. There are two mains levels to
 * generate:
 *   1. The climb part or Mountain
 *   2. The summit part
 */
const RG = require('./rg.js');
const MapGenerator = require('./map.generator');
const Level = require('./level');
const Geometry = require('./geometry');
const Path = require('./path');
const DungeonPopulate = require('./dungeon-populate');

const MountainGenerator = function() {

};

MountainGenerator.options = {};

MountainGenerator.getSummitOptions = function() {
    return MountainGenerator.options.summit;
};
MountainGenerator.getFaceOptions = function() {
    const mapOpts = MapGenerator.getOptions('mountain');
    const opts = Object.assign({}, mapOpts, MountainGenerator.options.face);
    // Usually overridden by top-level conf
    opts.maxDanger = 5;
    opts.maxValue = 100;
    return opts;
};

MountainGenerator.options.face = {

};

MountainGenerator.options.summit = {
    ratio: 0.3
};

MountainGenerator.prototype.createFace = function(cols, rows, conf) {
    const mapgen = new MapGenerator();
    const level = new Level(cols, rows);
    mapgen.setGen('mountain', cols, rows);
    conf.nRoadTurns = 0;
    const mapObj = mapgen.createMountain(cols, rows, conf);
    const {paths} = mapObj;
    level.setMap(mapObj.map);

    this.createCrux(level, conf);
    level.setExtras({paths});
    return level;
};

MountainGenerator.prototype.createSummit = function(cols, rows, conf) {
    const mapgen = new MapGenerator();
    const level = new Level(cols, rows);
    mapgen.setGen('mountain', cols, rows);
    const mapObj = mapgen.createSummit(cols, rows, conf);
    level.setMap(mapObj.map);
    level.setExtras({});
    return level;
};

/* Creates the most difficult part of the level. */
MountainGenerator.prototype.createCrux = function(level, conf) {
    const map = level.getMap();
    const cols = map.cols;
    const wallRows = Math.round(map.rows / 6);
    const wallConf = {
        wallElem: RG.ELEM.HIGH_ROCK,
        meanWy: Math.round(wallRows / 2.5)
    };

    const mapgen = new MapGenerator();
    mapgen.setGen('wall', cols, wallRows);
    const wallMapObj = mapgen.createWall(cols, wallRows, wallConf);

    const wallMap = wallMapObj.map;
    wallMap.debugPrintInASCII();

    // Carve a path through the wall
    const xTop = RG.RAND.getUniformInt(0, cols - 1);
    const xBottom = RG.RAND.getUniformInt(0, cols - 1);
    const carvedXY = this.carvePath(wallMap, xTop, 0, xBottom, wallRows - 1);

    const wallStartY = Math.round(map.rows / 5);
    const mergeCb = (c1, c2) => {
        // const baseElem1 = c1.getBaseElem();
        const baseElem2 = c2.getBaseElem();
        return !(/(floor)/).test(baseElem2.getType());
    };
    Geometry.mergeMaps(map, wallMap, 0, wallStartY, mergeCb);

    // Create a path which goes through the level
    /* const bbox = {bbox: {
        ulx: 0, uly: wallStartY, lrx: cols - 1, lry: wallStartY + wallRows - 1
    }};*/
    const pathConf = {
        // exclude: bbox,
        startY: 0, maxY: wallStartY
    };
    console.log('mGen first path');
    let paths = mapgen.createMountainPath(map, pathConf);

    pathConf.startY = wallStartY + wallRows;
    pathConf.maxY = map.rows - 1;
    pathConf.startX = xBottom;
    console.log('mGen second path');
    paths = paths.concat(mapgen.createMountainPath(map, pathConf));

    level.addExtras('paths', paths);
    // Add some guardians to the crux points, offset Y-coord first
    carvedXY.forEach(xyCoord => {
        xyCoord[1] += wallStartY;
    });

    const nGuardians = 3;
    const dungPopul = new DungeonPopulate(conf);
    for (let i = 0; i < nGuardians; i++) {
        const guardPoint = RG.RAND.arrayGetRand(carvedXY);
        dungPopul.addPointGuardian(level, guardPoint, conf.maxDanger);
    }
};

/* Carves a path between x0,y0 and x1,y1 using a shortest distance. */
MountainGenerator.prototype.carvePath = function(map, x0, y0, x1, y1) {
    const result = [];
    const path = Path.getShortestPath(x0, y0, x1, y1);
    path.forEach(xy => {
        const brush = Geometry.getCrossAround(xy.x, xy.y, 2, true);
        brush.forEach(xy => {
            const [x, y] = xy;
            if (map.hasXY(x, y)) {
                result.push(xy);
                map.setBaseElemXY(x, y, RG.ELEM.STONE);
            }
        });
    });
    return result;
};

module.exports = MountainGenerator;
<commit_msg>Modified the path config params.<commit_after>
/* Contains code for generating mountain levels. There are two mains levels to
 * generate:
 *   1. The climb part or Mountain
 *   2. The summit part
 */
const RG = require('./rg.js');
const MapGenerator = require('./map.generator');
const Level = require('./level');
const Geometry = require('./geometry');
const Path = require('./path');
const DungeonPopulate = require('./dungeon-populate');

const MountainGenerator = function() {

};

MountainGenerator.options = {};

MountainGenerator.getSummitOptions = function() {
    return MountainGenerator.options.summit;
};
MountainGenerator.getFaceOptions = function() {
    const mapOpts = MapGenerator.getOptions('mountain');
    const opts = Object.assign({}, mapOpts, MountainGenerator.options.face);
    // Usually overridden by top-level conf
    opts.maxDanger = 5;
    opts.maxValue = 100;
    return opts;
};

MountainGenerator.options.face = {

};

MountainGenerator.options.summit = {
    ratio: 0.3
};

MountainGenerator.prototype.createFace = function(cols, rows, conf) {
    const mapgen = new MapGenerator();
    const level = new Level(cols, rows);
    mapgen.setGen('mountain', cols, rows);
    conf.nRoadTurns = 0;
    const mapObj = mapgen.createMountain(cols, rows, conf);
    const {paths} = mapObj;
    level.setMap(mapObj.map);

    this.createCrux(level, conf);
    level.setExtras({paths});
    return level;
};

MountainGenerator.prototype.createSummit = function(cols, rows, conf) {
    const mapgen = new MapGenerator();
    const level = new Level(cols, rows);
    mapgen.setGen('mountain', cols, rows);
    const mapObj = mapgen.createSummit(cols, rows, conf);
    level.setMap(mapObj.map);
    level.setExtras({});
    return level;
};

/* Creates the most difficult part of the level. */
MountainGenerator.prototype.createCrux = function(level, conf) {
    const map = level.getMap();
    const cols = map.cols;
    const wallRows = Math.round(map.rows / 6);
    const wallConf = {
        wallElem: RG.ELEM.HIGH_ROCK,
        meanWy: Math.round(wallRows / 2.5)
    };

    const mapgen = new MapGenerator();
    mapgen.setGen('wall', cols, wallRows);
    const wallMapObj = mapgen.createWall(cols, wallRows, wallConf);

    const wallMap = wallMapObj.map;
    wallMap.debugPrintInASCII();

    // Carve a path through the wall
    const xTop = RG.RAND.getUniformInt(0, cols - 1);
    const xBottom = RG.RAND.getUniformInt(0, cols - 1);
    const carvedXY = this.carvePath(wallMap, xTop, 0, xBottom, wallRows - 1);

    const wallStartY = Math.round(map.rows / 5);
    const mergeCb = (c1, c2) => {
        // const baseElem1 = c1.getBaseElem();
        const baseElem2 = c2.getBaseElem();
        return !(/(floor)/).test(baseElem2.getType());
    };
    Geometry.mergeMaps(map, wallMap, 0, wallStartY, mergeCb);

    // Create a path which goes through the level
    /* const bbox = {bbox: {
        ulx: 0, uly: wallStartY, lrx: cols - 1, lry: wallStartY + wallRows - 1
    }};*/
    const pathConf = {
        // exclude: bbox,
        startY: 0, maxY: wallStartY,
        yPerTurn: Math.round(wallStartY / 4),
        endX: xTop
    };
    console.log('mGen first path');
    let paths = mapgen.createMountainPath(map, pathConf);

    pathConf.startY = wallStartY + wallRows;
    pathConf.maxY = map.rows - 1;
    pathConf.startX = xBottom;
    pathConf.yPerTurn = 0;
    paths = paths.concat(mapgen.createMountainPath(map, pathConf));

    level.addExtras('paths', paths);
    // Add some guardians to the crux points, offset Y-coord first
    carvedXY.forEach(xyCoord => {
        xyCoord[1] += wallStartY;
    });

    const nGuardians = 3;
    const dungPopul = new DungeonPopulate(conf);
    for (let i = 0; i < nGuardians; i++) {
        const guardPoint = RG.RAND.arrayGetRand(carvedXY);
        dungPopul.addPointGuardian(level, guardPoint, conf.maxDanger);
    }
};

/* Carves a path between x0,y0 and x1,y1 using a shortest distance. */
MountainGenerator.prototype.carvePath = function(map, x0, y0, x1, y1) {
    const result = [];
    const path = Path.getShortestPath(x0, y0, x1, y1);
    path.forEach(xy => {
        const brush = Geometry.getCrossAround(xy.x, xy.y, 2, true);
        brush.forEach(xy => {
            const [x, y] = xy;
            if (map.hasXY(x, y)) {
                result.push(xy);
                map.setBaseElemXY(x, y, RG.ELEM.STONE);
            }
        });
    });
    return result;
};

module.exports = MountainGenerator;
<|endoftext|>


<commit_before>import React from 'react'
import Page from 'components/Page'
import {Alert, Table, Button, Col, DropdownButton, MenuItem, Modal} from 'react-bootstrap'
import autobind from 'autobind-decorator'
import moment from 'moment'

import {Report, Person, Poam} from 'models'
import Breadcrumbs from 'components/Breadcrumbs'
import Form from 'components/Form'
import LinkTo from 'components/LinkTo'
import History from 'components/History'

import API from 'api'

const atmosphereIconCss = {
	fontSize: '2rem',
	display: 'inline-block',
	marginTop: '-4px',
	marginRight: '1rem',
}

const atmosphereIcons = {
	'POSITIVE': "👍",
	'NEUTRAL': "😐",
	'NEGATIVE': "👎",
}

const commentFormCss = {
	marginTop: '50px',
}

const approvalButtonCss = {
	marginLeft: '15px',
}

export default class ReportShow extends Page {
	static contextTypes = {
		app: React.PropTypes.object,
	}

	constructor(props) {
		super(props)
		this.state = {
			report: new Report({id: props.params.id}),

			newComment: {
				text: '',
			},
		}
	}

	fetchData(props) {
		API.query(/* GraphQL */`
			report(id:${props.params.id}) {
				id, intent, engagementDate, atmosphere, atmosphereDetails
				keyOutcomesSummary, keyOutcomes, nextStepsSummary, reportText, nextSteps

				state

				location { id, name }
				author {
					id, name
					position {
						organization {
							name
							approvalSteps {
								id
								approverGroup {
									id, name
									members { id, name, rank }
								}
							}
						}
					}
				}

				attendees {
					id, name, role, primary
					position { id, name }
				}
				primaryAdvisor { id }
				primaryPrincipal { id }

				poams { id, shortName, longName, responsibleOrg { id, name} }

				comments {
					id, text, createdAt, updatedAt
					author { id, name, rank }
				}

				principalOrg { id, name }
				advisorOrg { id, name }

				approvalStatus {
					type, createdAt
					step { id ,
						approverGroup {
							id, name,
							members { id, name }
						}
					},
					person { id, name, rank}
				}

				approvalStep {
					approverGroup {
						members { id }
					}
				}
			}
		`).then(data => this.setState({report: new Report(data.report)}))
	}

	render() {
		let {report} = this.state
		let {currentUser} = this.context.app.state

		let canApprove = report.isPending() && (currentUser.isAdmin() ||
			report.approvalStep.approverGroup.members.find(member => member.id === currentUser.id))

		//Authors can approve in draft mode or Pending Mode
		let canEdit = (report.isDraft() || report.isPending()) && (currentUser.id === report.author.id)
		//Approvers can edit.
		canEdit = canEdit || canApprove

		//Only the author can submit when report is in Draft.
		let canSubmit = report.isDraft() && (currentUser.id === report.author.id)

		//Anbody can email a report as long as it's not in draft.
		let canEmail = !report.isDraft();

		let errors = report.isDraft() && report.validateForSubmit();

		return (

				<Breadcrumbs items={[['Reports', '/reports'], [report.intent || 'Report #' + report.id, Report.pathFor(report)]]} />

				{report.isDraft() &&
					<fieldset style={{textAlign: 'center'}}>

This report is in DRAFT state and hasn't been submitted.

You can review the draft below to make sure all the details are correct.

							{errors && errors.length > 0 &&
								this.renderValidationErrors(errors)
							}

					</fieldset>
				}

				{report.isPending() &&
					<fieldset style={{textAlign: 'center'}}>

This report is PENDING approvals.

It won't be available in the ANET database until your approval organization marks it as approved.

					</fieldset>
				}

					<DropdownButton bsStyle="primary" title="Actions" id="actions"
							className="pull-right" onSelect={this.actionSelect}>
						{canEdit && <MenuItem eventKey="edit" >Edit Report</MenuItem>}
						{canSubmit && errors.length === 0 && <MenuItem eventKey="submit">Submit</MenuItem>}
						{canEmail && <MenuItem eventKey="email" className="todo" >Email Report</MenuItem>}
					</DropdownButton>

				<Form static formFor={report} horizontal>
					{this.state.error &&
						<fieldset className="text-danger">

There was a problem saving this report.

{this.state.error}

						</fieldset>
					}

					<fieldset>
						<legend>Report #{report.id}</legend>

						<Form.Field id="intent" label="Subject" />
						<Form.Field id="engagementDate" label="Date 📆" getter={date => moment(date).format("L")} />
						<Form.Field id="location" label="Location 📍">
							{report.location && <LinkTo location={report.location} />}
						</Form.Field>
						<Form.Field id="atmosphere" label="Atmospherics">
							{atmosphereIcons[report.atmosphere]}
							{report.atmosphereDetails}
						</Form.Field>
						<Form.Field id="author" label="Report author">
							<LinkTo person={report.author} />
						</Form.Field>
						<Form.Field id="advisorOrg" label="Advisor Org">
							<LinkTo organization={report.advisorOrg} />
						</Form.Field>
						<Form.Field id="principalOrg" label="Principal Org">
							<LinkTo organization={report.principalOrg} />
						</Form.Field>
					</fieldset>

					<fieldset>
						<legend>Meeting attendees</legend>

									Primary
									Name
									Type
									Position

								{Person.map(report.attendees, person =>

											{person.primary &&
												"⭐"
											}

										<LinkTo person={person} />
										{person.role}
										<LinkTo position={person.position} />

								)}

					</fieldset>

					<fieldset>
						<legend>Plan of Action and Milestones / Pillars</legend>

									Name
									Organization

								{Poam.map(report.poams, poam =>

										<LinkTo poam={poam} />
										<LinkTo organization={poam.responsibleOrg} />

								)}

					</fieldset>

					<fieldset>
						<legend>Meeting discussion</legend>

Key outcomes

						{report.keyOutcomesSummary}

Next steps

						{report.nextStepsSummary}

Report Details

					</fieldset>

					{report.isPending() &&
						<fieldset>

							<legend>Approvals</legend>

							{report.approvalStatus.map(action =>
								this.renderApprovalAction(action)
							)}

							{canApprove &&

									<Button bsStyle="danger" style={approvalButtonCss} onClick={this.rejectReport}>Reject</Button>
									<Button bsStyle="warning" style={approvalButtonCss} onClick={this.actionSelect.bind(this, "edit")} >Edit report</Button>
									<Button bsStyle="primary" style={approvalButtonCss} onClick={this.approveReport}>Approve</Button>

							}
						</fieldset>
					}

					{canSubmit &&
						<fieldset>
							<Col md={9}>
								{(errors && errors.length > 0) ?
									this.renderValidationErrors(errors)
									:

										By pressing submit, this report will be sent to
										 {Object.get(report, 'author.position.organization.name') || 'your organization approver'}
										to go through the approval workflow.

								}
							</Col>

							<Col md={3}>
								<Button type="submit" bsStyle="primary" bsSize="large"
										onClick={this.submitDraft}
										disabled={errors && errors.length > 0} >
									Submit report
								</Button>
							</Col>
						</fieldset>
					}

					<fieldset>
						<legend>Comments</legend>

						{report.comments.map(comment => {
							let createdAt = moment(comment.createAt)
							return (

									<LinkTo person={comment.author} />
									 {createdAt.fromNow()}:
									"{comment.text}"

							)
						})}

						{!report.comments.length && "There are no comments yet."}

						<Form formFor={this.state.newComment} horizontal style={commentFormCss}>
							<Form.Field id="text" placeholder="Type a comment here" label="">
								<Form.Field.ExtraCol>
									<Button bsStyle="primary" type="submit">Save comment</Button>
								</Form.Field.ExtraCol>
							</Form.Field>
						</Form>
					</fieldset>
				</Form>

		)
	}

	@autobind
	submitDraft() {
		API.send(`/api/reports/${this.state.report.id}/submit`).then(this.updateReport, this.handleError)
	}

	@autobind
	rejectReport() {
		let comment = {
			text: "TODO"
		}

		API.send(`/api/reports/${this.state.report.id}/reject`, comment).then(this.updateReport, this.handleError)
	}

	@autobind
	approveReport() {
		API.send(`/api/reports/${this.state.report.id}/approve`).then(this.updateReport, this.handleError)
	}

	@autobind
	updateReport(json) {
		this.fetchData(this.props)
		window.scrollTo(0, 0)
	}

	@autobind
	handleError(response) {
		this.setState({error: response.error})
		window.scrollTo(0, 0)
	}

	@autobind
	actionSelect(eventKey, event) {
		if (eventKey === "edit") {
			History.push(`/reports/${this.state.report.id}/edit`);
		} else if (eventKey === "submit" ) {
			this.submitDraft()
		} else {
			console.log("Unimplemented Action: " + eventKey);
		}
	}

	@autobind
	renderApprovalAction(action) {
		let group = action.step.approverGroup
		return

			<Button onClick={this.showApproversModal.bind(this, group)}>
				{group.name}
			</Button>
			<Modal show={group.showModal} onHide={this.closeApproversModal.bind(this, group)}>
				<Modal.Header closeButton>
					<Modal.Title>Approvers for {group.name}</Modal.Title>
				</Modal.Header>
				<Modal.Body>

					{group.members.map(p =>

{p.name} - {p.emailAddress}

					)}

				</Modal.Body>
			</Modal>
	 	{action.type ?
				 {action.type} by {action.person.name} {moment(action.createdAt).format("L")}
				:
				 Pending
			}

	}

	renderValidationErrors(errors) {
		return <Alert bsStyle="danger">
			The following errors must be fixed before submitting this report

			{ errors.map((error,idx) =>

{error}

			)}

		</Alert>
	}

	@autobind
	showApproversModal(approverGroup) {
		approverGroup.showModal = true
		this.setState(this.state)
	}

	@autobind
	closeApproversModal(approverGroup) {
		approverGroup.showModal = false
		this.setState(this.state)
	}
}
<commit_msg>Email action enabled, needs template<commit_after>import React from 'react'
import Page from 'components/Page'
import {Alert, Table, Button, Col, DropdownButton, MenuItem, Modal} from 'react-bootstrap'
import autobind from 'autobind-decorator'
import moment from 'moment'

import {Report, Person, Poam} from 'models'
import Breadcrumbs from 'components/Breadcrumbs'
import Form from 'components/Form'
import LinkTo from 'components/LinkTo'
import History from 'components/History'

import API from 'api'

const atmosphereIconCss = {
	fontSize: '2rem',
	display: 'inline-block',
	marginTop: '-4px',
	marginRight: '1rem',
}

const atmosphereIcons = {
	'POSITIVE': "👍",
	'NEUTRAL': "😐",
	'NEGATIVE': "👎",
}

const commentFormCss = {
	marginTop: '50px',
}

const approvalButtonCss = {
	marginLeft: '15px',
}

export default class ReportShow extends Page {
	static contextTypes = {
		app: React.PropTypes.object,
	}

	constructor(props) {
		super(props)
		this.state = {
			report: new Report({id: props.params.id}),

			newComment: {
				text: '',
			},
		}
	}

	fetchData(props) {
		API.query(/* GraphQL */`
			report(id:${props.params.id}) {
				id, intent, engagementDate, atmosphere, atmosphereDetails
				keyOutcomesSummary, keyOutcomes, nextStepsSummary, reportText, nextSteps

				state

				location { id, name }
				author {
					id, name
					position {
						organization {
							name
							approvalSteps {
								id
								approverGroup {
									id, name
									members { id, name, rank }
								}
							}
						}
					}
				}

				attendees {
					id, name, role, primary
					position { id, name }
				}
				primaryAdvisor { id }
				primaryPrincipal { id }

				poams { id, shortName, longName, responsibleOrg { id, name} }

				comments {
					id, text, createdAt, updatedAt
					author { id, name, rank }
				}

				principalOrg { id, name }
				advisorOrg { id, name }

				approvalStatus {
					type, createdAt
					step { id ,
						approverGroup {
							id, name,
							members { id, name }
						}
					},
					person { id, name, rank}
				}

				approvalStep {
					approverGroup {
						members { id }
					}
				}
			}
		`).then(data => this.setState({report: new Report(data.report)}))
	}

	render() {
		let {report} = this.state
		let {currentUser} = this.context.app.state

		let canApprove = report.isPending() && (currentUser.isAdmin() ||
			report.approvalStep.approverGroup.members.find(member => member.id === currentUser.id))

		//Authors can approve in draft mode or Pending Mode
		let canEdit = (report.isDraft() || report.isPending()) && (currentUser.id === report.author.id)
		//Approvers can edit.
		canEdit = canEdit || canApprove

		//Only the author can submit when report is in Draft.
		let canSubmit = report.isDraft() && (currentUser.id === report.author.id)

		//Anbody can email a report as long as it's not in draft.
		let canEmail = !report.isDraft();

		let errors = report.isDraft() && report.validateForSubmit();

		return (

				<Breadcrumbs items={[['Reports', '/reports'], [report.intent || 'Report #' + report.id, Report.pathFor(report)]]} />

				{report.isDraft() &&
					<fieldset style={{textAlign: 'center'}}>

This report is in DRAFT state and hasn't been submitted.

You can review the draft below to make sure all the details are correct.

							{errors && errors.length > 0 &&
								this.renderValidationErrors(errors)
							}

					</fieldset>
				}

				{report.isPending() &&
					<fieldset style={{textAlign: 'center'}}>

This report is PENDING approvals.

It won't be available in the ANET database until your approval organization marks it as approved.

					</fieldset>
				}

					<DropdownButton bsStyle="primary" title="Actions" id="actions"
							className="pull-right" onSelect={this.actionSelect}>
						{canEdit && <MenuItem eventKey="edit" >Edit Report</MenuItem>}
						{canSubmit && errors.length === 0 && <MenuItem eventKey="submit">Submit</MenuItem>}
						{canEmail && <MenuItem eventKey="email" className="todo" href={"mailto:" + "?subject="+encodeURIComponent(this.state.report.intent)+"&body="+encodeURIComponent(this.state.report.reportText)}>Email Report</MenuItem>}
					</DropdownButton>

				<Form static formFor={report} horizontal>
					{this.state.error &&
						<fieldset className="text-danger">

There was a problem saving this report.

{this.state.error}

						</fieldset>
					}

					<fieldset>
						<legend>Report #{report.id}</legend>

						<Form.Field id="intent" label="Subject" />
						<Form.Field id="engagementDate" label="Date 📆" getter={date => moment(date).format("L")} />
						<Form.Field id="location" label="Location 📍">
							{report.location && <LinkTo location={report.location} />}
						</Form.Field>
						<Form.Field id="atmosphere" label="Atmospherics">
							{atmosphereIcons[report.atmosphere]}
							{report.atmosphereDetails}
						</Form.Field>
						<Form.Field id="author" label="Report author">
							<LinkTo person={report.author} />
						</Form.Field>
						<Form.Field id="advisorOrg" label="Advisor Org">
							<LinkTo organization={report.advisorOrg} />
						</Form.Field>
						<Form.Field id="principalOrg" label="Principal Org">
							<LinkTo organization={report.principalOrg} />
						</Form.Field>
					</fieldset>

					<fieldset>
						<legend>Meeting attendees</legend>

									Primary
									Name
									Type
									Position

								{Person.map(report.attendees, person =>

											{person.primary &&
												"⭐"
											}

										<LinkTo person={person} />
										{person.role}
										<LinkTo position={person.position} />

								)}

					</fieldset>

					<fieldset>
						<legend>Plan of Action and Milestones / Pillars</legend>

									Name
									Organization

								{Poam.map(report.poams, poam =>

										<LinkTo poam={poam} />
										<LinkTo organization={poam.responsibleOrg} />

								)}

					</fieldset>

					<fieldset>
						<legend>Meeting discussion</legend>

Key outcomes

						{report.keyOutcomesSummary}

Next steps

						{report.nextStepsSummary}

Report Details

					</fieldset>

					{report.isPending() &&
						<fieldset>

							<legend>Approvals</legend>

							{report.approvalStatus.map(action =>
								this.renderApprovalAction(action)
							)}

							{canApprove &&

									<Button bsStyle="danger" style={approvalButtonCss} onClick={this.rejectReport}>Reject</Button>
									<Button bsStyle="warning" style={approvalButtonCss} onClick={this.actionSelect.bind(this, "edit")} >Edit report</Button>
									<Button bsStyle="primary" style={approvalButtonCss} onClick={this.approveReport}>Approve</Button>

							}
						</fieldset>
					}

					{canSubmit &&
						<fieldset>
							<Col md={9}>
								{(errors && errors.length > 0) ?
									this.renderValidationErrors(errors)
									:

										By pressing submit, this report will be sent to
										 {Object.get(report, 'author.position.organization.name') || 'your organization approver'}
										to go through the approval workflow.

								}
							</Col>

							<Col md={3}>
								<Button type="submit" bsStyle="primary" bsSize="large"
										onClick={this.submitDraft}
										disabled={errors && errors.length > 0} >
									Submit report
								</Button>
							</Col>
						</fieldset>
					}

					<fieldset>
						<legend>Comments</legend>

						{report.comments.map(comment => {
							let createdAt = moment(comment.createAt)
							return (

									<LinkTo person={comment.author} />
									 {createdAt.fromNow()}:
									"{comment.text}"

							)
						})}

						{!report.comments.length && "There are no comments yet."}

						<Form formFor={this.state.newComment} horizontal style={commentFormCss}>
							<Form.Field id="text" placeholder="Type a comment here" label="">
								<Form.Field.ExtraCol>
									<Button bsStyle="primary" type="submit">Save comment</Button>
								</Form.Field.ExtraCol>
							</Form.Field>
						</Form>
					</fieldset>
				</Form>

		)
	}

	@autobind
	submitDraft() {
		API.send(`/api/reports/${this.state.report.id}/submit`).then(this.updateReport, this.handleError)
	}

	@autobind
	rejectReport() {
		let comment = {
			text: "TODO"
		}

		API.send(`/api/reports/${this.state.report.id}/reject`, comment).then(this.updateReport, this.handleError)
	}

	@autobind
	approveReport() {
		API.send(`/api/reports/${this.state.report.id}/approve`).then(this.updateReport, this.handleError)
	}

	@autobind
	updateReport(json) {
		this.fetchData(this.props)
		window.scrollTo(0, 0)
	}

	@autobind
	handleError(response) {
		this.setState({error: response.error})
		window.scrollTo(0, 0)
	}

	@autobind
	actionSelect(eventKey, event) {
		if (eventKey === "edit") {
			History.push(`/reports/${this.state.report.id}/edit`);
		} else if (eventKey === "submit" ) {
			this.submitDraft()
		} else if (eventKey === "email" ) {
		} else {
			console.log("Unimplemented Action: " + eventKey);
		}
	}

	@autobind
	renderApprovalAction(action) {
		let group = action.step.approverGroup
		return

			<Button onClick={this.showApproversModal.bind(this, group)}>
				{group.name}
			</Button>
			<Modal show={group.showModal} onHide={this.closeApproversModal.bind(this, group)}>
				<Modal.Header closeButton>
					<Modal.Title>Approvers for {group.name}</Modal.Title>
				</Modal.Header>
				<Modal.Body>

					{group.members.map(p =>

{p.name} - {p.emailAddress}

					)}

				</Modal.Body>
			</Modal>
	 	{action.type ?
				 {action.type} by {action.person.name} {moment(action.createdAt).format("L")}
				:
				 Pending
			}

	}

	renderValidationErrors(errors) {
		return <Alert bsStyle="danger">
			The following errors must be fixed before submitting this report

			{ errors.map((error,idx) =>

{error}

			)}

		</Alert>
	}

	@autobind
	showApproversModal(approverGroup) {
		approverGroup.showModal = true
		this.setState(this.state)
	}

	@autobind
	closeApproversModal(approverGroup) {
		approverGroup.showModal = false
		this.setState(this.state)
	}
}
<|endoftext|>


<commit_before>"use strict";

var page = require('./page')();
var TipboxApi = require('./api');
var Tip = require('./tip');
var utils = require('./utils');
var server_pgp = require('../../../keys/public.key.json');

var api = new TipboxApi({pgp: server_pgp});

if(window.currentView == "composeView") {

  var $sendBtn = document.querySelector('#sendBtn');

  /*
   * Params
   */
  var params = {
      recipient: utils.getParam('recipient')
    , subject: utils.getParam('subject', 'No subject')
    , signature: utils.getParam('signature')
    , fingerprint: utils.getParam('fingerprint')
  }

  var els = document.querySelectorAll('[data-attr]');
  for(var i=0;i<els.length;i++) {
    var el = els[i];
    var attr = el.dataset.attr;
    if(el.attributes.title) {
      el.setAttribute('title', params[attr]);
    }
    if(params[attr]) el.textContent = params[attr];
  }

  var tip;
  var options = {
      el: document.querySelector('#tip')
    , recipient: params.recipient
    , subject: params.subject
    , signature: params.signature
    , api: api
  };

  if(params.fingerprint && params.fingerprint.length == 40) {
    api.pgp.get(params.fingerprint, function(err, recipient_pgp) {
      options.pgp = recipient_pgp;
      options.fingerprint = params.fingerprint;
      tip = new Tip(options);
    });
  }
  else {
    tip = new Tip(options);
  }

  $sendBtn.addEventListener('click', function(e) {
    e.preventDefault();
    tip.send();
    return false;
  });

}

if(window.currentView == "createView") {

  var createViewElem = document.getElementById('createView');
  var $recipient = createViewElem.querySelector('#recipient');
  var $subject = createViewElem.querySelector('#subject');
  var $createBtn = createViewElem.querySelector('#createBtn');
  var $errorlog = createViewElem.querySelector('#errorlog');
  var $tipboxCreated = createViewElem.querySelector('#tipboxCreated');
  var $encryptionInfo = createViewElem.querySelector('#encryptionInfo');
  var $selectPGP = createViewElem.querySelector('#selectPGP');
  var $agreeToS = createViewElem.querySelector('#agreeToS');

  var searchPGP = function() {
    var recipient = $recipient.value;
    if(!utils.isEmail(recipient)) return;

    var $spinner = document.querySelector('#encryption .spinner');
    $spinner.classList.remove('hidden');
    api.pgp.search(recipient, function(err, results) {
      $spinner.classList.add('hidden');
      $selectPGP.innerHTML = '';

      if(err || !results || results.length == 0) {
        $encryptionInfo.classList.remove('hidden');
        return;
      }

      selectedKey = null;
      if(results.length > 0) {
        $encryptionInfo.classList.add('hidden');
        $selectPGP.appendChild(createSelectableListElement("No encryption", null));

        for(var i=0; i < results.length; i++) {
          var key = new Key(results[i]);
          $selectPGP.appendChild(key.toElement());
        }
      }
    });
  };

  var recipient = utils.getParam('recipient');
  if(recipient) {
    $recipient.value = recipient;
    searchPGP();
    $subject.focus();
  }

  var Key = function(key) {
    this.fingerprint = key.fingerprint;
    this.date = key.date;
    this.bits = key.bits;
  }

  Key.prototype.toString = function() {
    return "0x"+this.fingerprint.substr(32)+" ("+this.date.slice(0,-5).replace('T',' ')+")";
  }

  var selectedKey = null;

  var selectKey = function(el, value) {
    if(selectedKey)
      selectedKey.el.classList.toggle('selected');

    selectedKey = { el: el, value: value };
    el.classList.toggle('selected');
  };

  var showError = function(msg) {
    $errorlog.querySelector('span').textContent = msg;
    $errorlog.classList.remove('hidden');
  };

  var createSelectableListElement = function(label, value) {
    var li = document.createElement('li');
    var a = document.createElement('a');

    // Select the first encryption key found
    if(!selectedKey || !selectedKey.value) {
      selectKey(a, value);
    }

    a.addEventListener('click', function(e) {
      e.preventDefault();
      selectKey(this, value);
      return false;
    });

    li.className = 'table-view-cell media';
    a.innerHTML = ''+label;
    li.appendChild(a);

    return li;

  };

  Key.prototype.toElement = function() {
    return createSelectableListElement(this.toString(),this.fingerprint);
  }

  $recipient.addEventListener('blur', searchPGP);

  $createBtn.addEventListener('click', function(e) {
    e.preventDefault();

    var recipient = $recipient.value;
    var subject = $subject.value;
    var fingerprint = (selectedKey) ? selectedKey.value : '';

    if(!utils.isEmail(recipient))
      return showError("Invalid email address");

    if(!$agreeToS.checked)
      return showError("You must accept our Terms of Service and Privacy Policy.");

    if(!subject)
      return showError("Subject cannot be empty");

    api.tipbox.create(recipient, subject, fingerprint, function(err, res) {
      if(err) {
        console.error("Error creating the tipbox", err);
        return;
      }

      $tipboxCreated.classList.toggle('active');
    });

    return false;
  });

}
<commit_msg>Making sure we add the blur event when coming from the homepage<commit_after>"use strict";

var page = require('./page')();
var TipboxApi = require('./api');
var Tip = require('./tip');
var utils = require('./utils');
var server_pgp = require('../../../keys/public.key.json');

var api = new TipboxApi({pgp: server_pgp});

//
// ComposeView Controller
//
var ComposeViewController = (function() {
  var $sendBtn = document.querySelector('#sendBtn');

  /*
   * Params
   */
  var params = {
      recipient: utils.getParam('recipient')
    , subject: utils.getParam('subject', 'No subject')
    , signature: utils.getParam('signature')
    , fingerprint: utils.getParam('fingerprint')
  }

  var els = document.querySelectorAll('[data-attr]');
  for(var i=0;i<els.length;i++) {
    var el = els[i];
    var attr = el.dataset.attr;
    if(el.attributes.title) {
      el.setAttribute('title', params[attr]);
    }
    if(params[attr]) el.textContent = params[attr];
  }

  var tip;
  var options = {
      el: document.querySelector('#tip')
    , recipient: params.recipient
    , subject: params.subject
    , signature: params.signature
    , api: api
  };

  if(params.fingerprint && params.fingerprint.length == 40) {
    api.pgp.get(params.fingerprint, function(err, recipient_pgp) {
      options.pgp = recipient_pgp;
      options.fingerprint = params.fingerprint;
      tip = new Tip(options);
    });
  }
  else {
    tip = new Tip(options);
  }

  $sendBtn.addEventListener('click', function(e) {
    e.preventDefault();
    tip.send();
    return false;
  });
})();

//
// CreateView Controller
//
var CreateViewController = (function() {
  var createViewElem = document.getElementById('createView');
  var $recipient = createViewElem.querySelector('#recipient');
  var $subject = createViewElem.querySelector('#subject');
  var $createBtn = createViewElem.querySelector('#createBtn');
  var $errorlog = createViewElem.querySelector('#errorlog');
  var $tipboxCreated = createViewElem.querySelector('#tipboxCreated');
  var $encryptionInfo = createViewElem.querySelector('#encryptionInfo');
  var $selectPGP = createViewElem.querySelector('#selectPGP');
  var $agreeToS = createViewElem.querySelector('#agreeToS');

  var searchPGP = function() {
    var recipient = $recipient.value;
    if(!utils.isEmail(recipient)) return;

    var $spinner = document.querySelector('#encryption .spinner');
    $spinner.classList.remove('hidden');
    api.pgp.search(recipient, function(err, results) {
      $spinner.classList.add('hidden');
      $selectPGP.innerHTML = '';

      if(err || !results || results.length == 0) {
        $encryptionInfo.classList.remove('hidden');
        return;
      }

      selectedKey = null;
      if(results.length > 0) {
        $encryptionInfo.classList.add('hidden');
        $selectPGP.appendChild(createSelectableListElement("No encryption", null));

        for(var i=0; i < results.length; i++) {
          var key = new Key(results[i]);
          $selectPGP.appendChild(key.toElement());
        }
      }
    });
  };

  var recipient = utils.getParam('recipient');
  if(recipient) {
    $recipient.value = recipient;
    searchPGP();
    $subject.focus();
  }

  var Key = function(key) {
    this.fingerprint = key.fingerprint;
    this.date = key.date;
    this.bits = key.bits;
  }

  Key.prototype.toString = function() {
    return "0x"+this.fingerprint.substr(32)+" ("+this.date.slice(0,-5).replace('T',' ')+")";
  }

  var selectedKey = null;

  var selectKey = function(el, value) {
    if(selectedKey)
      selectedKey.el.classList.toggle('selected');

    selectedKey = { el: el, value: value };
    el.classList.toggle('selected');
  };

  var showError = function(msg) {
    $errorlog.querySelector('span').textContent = msg;
    $errorlog.classList.remove('hidden');
  };

  var createSelectableListElement = function(label, value) {
    var li = document.createElement('li');
    var a = document.createElement('a');

    // Select the first encryption key found
    if(!selectedKey || !selectedKey.value) {
      selectKey(a, value);
    }

    a.addEventListener('click', function(e) {
      e.preventDefault();
      selectKey(this, value);
      return false;
    });

    li.className = 'table-view-cell media';
    a.innerHTML = ''+label;
    li.appendChild(a);

    return li;

  };

  Key.prototype.toElement = function() {
    return createSelectableListElement(this.toString(),this.fingerprint);
  }

  $recipient.addEventListener('blur', searchPGP);

  $createBtn.addEventListener('click', function(e) {
    e.preventDefault();

    var recipient = $recipient.value;
    var subject = $subject.value;
    var fingerprint = (selectedKey) ? selectedKey.value : '';

    if(!utils.isEmail(recipient))
      return showError("Invalid email address");

    if(!$agreeToS.checked)
      return showError("You must accept our Terms of Service and Privacy Policy.");

    if(!subject)
      return showError("Subject cannot be empty");

    api.tipbox.create(recipient, subject, fingerprint, function(err, res) {
      if(err) {
        console.error("Error creating the tipbox", err);
        return;
      }

      $tipboxCreated.classList.toggle('active');
    });

    return false;
  });
})();
<|endoftext|>


<commit_before>var ServerConnection = require('logux-sync').ServerConnection
var MemoryStore = require('logux-core').MemoryStore
var WebSocket = require('ws')
var shortid = require('shortid')
var https = require('https')
var yargs = require('yargs')
var http = require('http')
var path = require('path')
var Log = require('logux-core').Log
var fs = require('fs')

var remoteAddress = require('./remote-address')
var promisify = require('./promisify')
var Client = require('./client')

yargs
  .option('h', {
    alias: 'host',
    describe: 'Host to bind server.',
    type: 'string'
  })
  .option('p', {
    alias: 'port',
    describe: 'Port to bind server',
    type: 'number'
  })
  .option('k', {
    alias: 'key',
    describe: 'Path to SSL key ',
    type: 'string'
  })
  .option('c', {
    alias: 'cert',
    describe: 'Path to SSL certificate',
    type: 'string'
  })
  .epilog(
    'Corresponding ENV variables: LOGUX_HOST, LOGUX_PORT, LOGUX_KEY, LOGUX_CERT'
  )
  .example('$0 --port 31337 --host 127.0.0.1')
  .example('LOGUX_PORT=1337 $0')
  .locale('en')
  .help()
yargs.argv

var PEM_PREAMBLE = '-----BEGIN'

function isPem (content) {
  if (typeof content === 'object' && content.pem) {
    return true
  } else {
    return content.toString().trim().indexOf(PEM_PREAMBLE) === 0
  }
}

function readFile (root, file) {
  file = file.toString()
  if (!path.isAbsolute(file)) {
    file = path.join(root, file)
  }
  return promisify(done => {
    fs.readFile(file, done)
  })
}

/**
 * Basic Logux Server API without good UI. Use it only if you need
 * to create some special hacks on top of Logux Server.
 *
 * In most use cases you should use {@link Server}.
 *
 * @param {object} options Server options.
 * @param {string} options.subprotocol Server current application
 *                                     subprotocol version in SemVer format.
 * @param {string} options.supports npm’s version requirements for client
 *                                  subprotocol version.
 * @param {string|number} [options.nodeId] Unique server ID. Be default,
 *                                         `server:` with compacted UUID.
 * @param {string} [options.root=process.cwd()] Application root to load files
 *                                              and show errors.
 * @param {number} [options.timeout=20000] Timeout in milliseconds
 *                                         to disconnect connection.
 * @param {number} [options.ping=10000] Milliseconds since last message to test
 *                                      connection by sending ping.
 * @param {Store} [options.store] Store to save log. Will be `MemoryStore`,
 *                                by default.
 * @param {"production"|"development"} [options.env] Development or production
 *                                                   server mode. By default,
 *                                                   it will be taken from
 *                                                   `NODE_ENV` environment
 *                                                   variable. On empty
 *                                                   `NODE_ENV` it will
 *                                                   be `"development"`.
 * @param {number} [options.pid] Process ID, to display in reporter.
 * @param {function} [reporter] Function to show current server status.
 *
 * @example
 * import { BaseServer } from 'logux-server'
 * class MyLoguxHack extends BaseServer {
 *   …
 * }
 *
 * @class
 */
function BaseServer (options, reporter) {
  /**
   * Server options.
   * @type {object}
   *
   * @example
   * console.log(app.options.nodeId + ' was started')
   */
  this.options = options || { }

  this.reporter = reporter || function () { }

  if (typeof this.options.subprotocol === 'undefined') {
    throw new Error('Missed subprotocol version')
  }
  if (typeof this.options.supports === 'undefined') {
    throw new Error('Missed supported subprotocol major versions')
  }

  if (typeof this.options.nodeId === 'undefined') {
    this.options.nodeId = `server:${ shortid.generate() }`
  }

  this.options.root = this.options.root || process.cwd()

  var store = this.options.store || new MemoryStore()

  /**
   * Server actions log.
   * @type {Log}
   *
   * @example
   * app.log.each(finder)
   */
  this.log = new Log({ store, nodeId: this.options.nodeId })

  this.log.on('before', (action, meta) => {
    if (!meta.server) meta.server = this.options.nodeId
  })

  /**
   * Production or development mode.
   * @type {"production"|"development"}
   *
   * @example
   * if (app.env === 'development') {
   *   logDebugData()
   * }
   */
  this.env = this.options.env || process.env.NODE_ENV || 'development'

  this.unbind = []

  /**
   * Connected clients.
   * @type {Client[]}
   *
   * @example
   * for (let nodeId in app.clients) {
   *   console.log(app.clients[nodeId].remoteAddress)
   * }
   */
  this.clients = { }
  this.actions = { }

  this.lastClient = 0

  var app = this
  this.unbind.push(() => {
    for (var i in app.clients) {
      app.clients[i].destroy()
    }
  })
}

BaseServer.prototype = {

  /**
   * Set authenticate function. It will receive client credentials
   * and node ID. It should return a Promise with `false`
   * on bad authentication or with any user data on correct credentials.
   *
   * @param {authenticator} authenticator The authentication callback.
   *
   * @return {undefined}
   *
   * @example
   * app.auth(token => {
   *   return findUserByToken(token).then(user => {
   *     return user.blocked ? false : user
   *   })
   * })
   */
  auth: function auth (authenticator) {
    this.authenticator = authenticator
  },

  /**
   * Start WebSocket server and listen for clients.
   *
   * @param {object} options Connection options.
   * @param {http.Server} [options.server] HTTP server to connect WebSocket
   *                                       server to it.
   *                                       Same as in ws.WebSocketServer.
   * @param {number} [option.port=1337] Port to bind server. It will create
   *                                    HTTP server manually to connect
   *                                    WebSocket server to it.
   * @param {string} [option.host="127.0.0.1"] IP-address to bind server.
   * @param {string} [option.key] SSL key or path to it. Path could be relative
   *                              from server root. It is required in production
   *                              mode, because WSS is highly recommended.
   * @param {string} [option.cert] SSL certificate or path to it. Path could
   *                               be relative from server root. It is required
   *                               in production mode, because WSS
   *                               is highly recommended.
   *
   * @return {Promise} When the server has been bound.
   *
   * @example
   * app.listen({ cert: 'cert.pem', key: 'key.pem' })
   */
  listen: function listen (options) {
    /**
     * Options used to start server.
     * @type {object}
     */
    this.listenOptions = options || { }

    if (this.listenOptions.key && !this.listenOptions.cert) {
      throw new Error('You must set cert option too if you use key option')
    }
    if (!this.listenOptions.key && this.listenOptions.cert) {
      throw new Error('You must set key option too if you use cert option')
    }

    if (!this.authenticator) {
      throw new Error('You must set authentication callback by app.auth()')
    }

    if (!this.listenOptions.server) {
      if (!this.listenOptions.port) this.listenOptions.port = 1337
      if (!this.listenOptions.host) this.listenOptions.host = '127.0.0.1'
    }

    var app = this
    var promise = Promise.resolve()

    if (this.listenOptions.server) {
      this.ws = new WebSocket.Server({ server: this.listenOptions.server })
    } else {
      var before = []
      if (this.listenOptions.key && !isPem(this.listenOptions.key)) {
        before.push(readFile(this.options.root, this.listenOptions.key))
      } else {
        before.push(Promise.resolve(this.listenOptions.key))
      }
      if (this.listenOptions.cert && !isPem(this.listenOptions.cert)) {
        before.push(readFile(this.options.root, this.listenOptions.cert))
      } else {
        before.push(Promise.resolve(this.listenOptions.cert))
      }

      promise = promise
        .then(() => Promise.all(before))
        .then(keys => new Promise((resolve, reject) => {
          if (keys[0]) {
            app.http = https.createServer({ key: keys[0], cert: keys[1] })
          } else {
            app.http = http.createServer()
          }

          app.ws = new WebSocket.Server({ server: app.http })

          app.ws.on('error', reject)

          var opts = app.listenOptions
          app.http.listen(opts.port, opts.host, resolve)
        }))
    }

    app.unbind.push(() => promisify(done => {
      promise.then(() => {
        app.ws.close(() => {
          if (app.http) {
            app.http.close(done)
          } else {
            done()
          }
        })
      })
    }))

    return promise.then(() => {
      app.ws.on('connection', ws => {
        app.reporter('connect', app, remoteAddress(ws))
        app.lastClient += 1
        var client = new Client(app, new ServerConnection(ws), app.lastClient)
        app.clients[app.lastClient] = client
      })
    }).then(() => {
      app.reporter('listen', app)
    })
  },

  /**
   * Stop server and unbind all listeners.
   *
   * @return {Promise} Promise when all listeners will be removed.
   *
   * @example
   * afterEach(() => {
   *   testApp.destroy()
   * })
   */
  destroy: function destroy () {
    this.destroing = true
    this.reporter('destroy', this)
    return Promise.all(this.unbind.map(i => i()))
  },

  /**
   * Load options from command-line arguments and/or environment
   *
   * @param {object} process Current process object.
   * @param {object} defaults Default options.
   * @return {object} Parsed options object.
   *
   * @example
   * app.listen(app.loadOptions(process, { port: 31337 }))
   */
  loadOptions: function loadOptions (process, defaults) {
    defaults = defaults || { }

    var argv = yargs.parse(process.argv)
    var env = process.env

    return {
      host: argv.h || env.LOGUX_HOST || defaults.host,
      port: parseInt(argv.p || env.LOGUX_PORT || defaults.port, 10),
      cert: argv.c || env.LOGUX_CERT || defaults.cert,
      key: argv.k || env.LOGUX_KEY || defaults.key
    }
  },

  /**
   * Define action type’s callbacks.
   *
   * @param {string} name The action’s type.
   * @param {object} callbacks Callbacks for actions with this type.
   * @param {authorizer} callback.access Check does user can do this action.
   * @param {processor} callback.process Action business logic.
   *
   * @return {undefined}
   *
   * @example
   * app.type('CHANGE_NAME', {
   *   access (action, meta, user) {
   *     return Promise.resolve(action.user === user.id)
   *   },
   *   process (action, meta) {
   *     if (isFirstOlder(lastNameChange(action.user), meta)) {
   *       return db.changeUserName({ id: action.user, name: action.name })
   *     }
   *   }
   * })
   */
  type: function type (name, callbacks) {
    if (this.actions[name]) {
      throw new Error(`Action type ${ name } was already defined`)
    }
    if (!callbacks || !callbacks.access) {
      throw new Error(`Action type ${ name } must have access callback`)
    }
    if (!callbacks.process) {
      throw new Error(`Action type ${ name } must have process callback`)
    }
    this.actions[name] = callbacks
  }

}

module.exports = BaseServer

/**
 * @callback authenticator
 * @param {string} id User ID.
 * @param {any} credentials The client credentials.
 * @param {Client} client Client object.
 * @return {Promise} Promise with `false` or user data.
 */

/**
 * @callback authorizer
 * @param {Action} action The action data.
 * @param {Meta} action The action metadata.
 * @param {Client} client The client object.
 * @return {Promise} Promise with `true` if client are allowed
 *                   to use this action.
 */

/**
 * @callback processor
 * @param {Action} action The action data.
 * @param {Meta} action The action metadata.
 * @param {Client} client The client object.
 * @return {Promise} Promise when processing will be finished.
 */
<commit_msg>Fix JSDoc for Server#type<commit_after>var ServerConnection = require('logux-sync').ServerConnection
var MemoryStore = require('logux-core').MemoryStore
var WebSocket = require('ws')
var shortid = require('shortid')
var https = require('https')
var yargs = require('yargs')
var http = require('http')
var path = require('path')
var Log = require('logux-core').Log
var fs = require('fs')

var remoteAddress = require('./remote-address')
var promisify = require('./promisify')
var Client = require('./client')

yargs
  .option('h', {
    alias: 'host',
    describe: 'Host to bind server.',
    type: 'string'
  })
  .option('p', {
    alias: 'port',
    describe: 'Port to bind server',
    type: 'number'
  })
  .option('k', {
    alias: 'key',
    describe: 'Path to SSL key ',
    type: 'string'
  })
  .option('c', {
    alias: 'cert',
    describe: 'Path to SSL certificate',
    type: 'string'
  })
  .epilog(
    'Corresponding ENV variables: LOGUX_HOST, LOGUX_PORT, LOGUX_KEY, LOGUX_CERT'
  )
  .example('$0 --port 31337 --host 127.0.0.1')
  .example('LOGUX_PORT=1337 $0')
  .locale('en')
  .help()
yargs.argv

var PEM_PREAMBLE = '-----BEGIN'

function isPem (content) {
  if (typeof content === 'object' && content.pem) {
    return true
  } else {
    return content.toString().trim().indexOf(PEM_PREAMBLE) === 0
  }
}

function readFile (root, file) {
  file = file.toString()
  if (!path.isAbsolute(file)) {
    file = path.join(root, file)
  }
  return promisify(done => {
    fs.readFile(file, done)
  })
}

/**
 * Basic Logux Server API without good UI. Use it only if you need
 * to create some special hacks on top of Logux Server.
 *
 * In most use cases you should use {@link Server}.
 *
 * @param {object} options Server options.
 * @param {string} options.subprotocol Server current application
 *                                     subprotocol version in SemVer format.
 * @param {string} options.supports npm’s version requirements for client
 *                                  subprotocol version.
 * @param {string|number} [options.nodeId] Unique server ID. Be default,
 *                                         `server:` with compacted UUID.
 * @param {string} [options.root=process.cwd()] Application root to load files
 *                                              and show errors.
 * @param {number} [options.timeout=20000] Timeout in milliseconds
 *                                         to disconnect connection.
 * @param {number} [options.ping=10000] Milliseconds since last message to test
 *                                      connection by sending ping.
 * @param {Store} [options.store] Store to save log. Will be `MemoryStore`,
 *                                by default.
 * @param {"production"|"development"} [options.env] Development or production
 *                                                   server mode. By default,
 *                                                   it will be taken from
 *                                                   `NODE_ENV` environment
 *                                                   variable. On empty
 *                                                   `NODE_ENV` it will
 *                                                   be `"development"`.
 * @param {number} [options.pid] Process ID, to display in reporter.
 * @param {function} [reporter] Function to show current server status.
 *
 * @example
 * import { BaseServer } from 'logux-server'
 * class MyLoguxHack extends BaseServer {
 *   …
 * }
 *
 * @class
 */
function BaseServer (options, reporter) {
  /**
   * Server options.
   * @type {object}
   *
   * @example
   * console.log(app.options.nodeId + ' was started')
   */
  this.options = options || { }

  this.reporter = reporter || function () { }

  if (typeof this.options.subprotocol === 'undefined') {
    throw new Error('Missed subprotocol version')
  }
  if (typeof this.options.supports === 'undefined') {
    throw new Error('Missed supported subprotocol major versions')
  }

  if (typeof this.options.nodeId === 'undefined') {
    this.options.nodeId = `server:${ shortid.generate() }`
  }

  this.options.root = this.options.root || process.cwd()

  var store = this.options.store || new MemoryStore()

  /**
   * Server actions log.
   * @type {Log}
   *
   * @example
   * app.log.each(finder)
   */
  this.log = new Log({ store, nodeId: this.options.nodeId })

  this.log.on('before', (action, meta) => {
    if (!meta.server) meta.server = this.options.nodeId
  })

  /**
   * Production or development mode.
   * @type {"production"|"development"}
   *
   * @example
   * if (app.env === 'development') {
   *   logDebugData()
   * }
   */
  this.env = this.options.env || process.env.NODE_ENV || 'development'

  this.unbind = []

  /**
   * Connected clients.
   * @type {Client[]}
   *
   * @example
   * for (let nodeId in app.clients) {
   *   console.log(app.clients[nodeId].remoteAddress)
   * }
   */
  this.clients = { }
  this.actions = { }

  this.lastClient = 0

  var app = this
  this.unbind.push(() => {
    for (var i in app.clients) {
      app.clients[i].destroy()
    }
  })
}

BaseServer.prototype = {

  /**
   * Set authenticate function. It will receive client credentials
   * and node ID. It should return a Promise with `false`
   * on bad authentication or with any user data on correct credentials.
   *
   * @param {authenticator} authenticator The authentication callback.
   *
   * @return {undefined}
   *
   * @example
   * app.auth(token => {
   *   return findUserByToken(token).then(user => {
   *     return user.blocked ? false : user
   *   })
   * })
   */
  auth: function auth (authenticator) {
    this.authenticator = authenticator
  },

  /**
   * Start WebSocket server and listen for clients.
   *
   * @param {object} options Connection options.
   * @param {http.Server} [options.server] HTTP server to connect WebSocket
   *                                       server to it.
   *                                       Same as in ws.WebSocketServer.
   * @param {number} [option.port=1337] Port to bind server. It will create
   *                                    HTTP server manually to connect
   *                                    WebSocket server to it.
   * @param {string} [option.host="127.0.0.1"] IP-address to bind server.
   * @param {string} [option.key] SSL key or path to it. Path could be relative
   *                              from server root. It is required in production
   *                              mode, because WSS is highly recommended.
   * @param {string} [option.cert] SSL certificate or path to it. Path could
   *                               be relative from server root. It is required
   *                               in production mode, because WSS
   *                               is highly recommended.
   *
   * @return {Promise} When the server has been bound.
   *
   * @example
   * app.listen({ cert: 'cert.pem', key: 'key.pem' })
   */
  listen: function listen (options) {
    /**
     * Options used to start server.
     * @type {object}
     */
    this.listenOptions = options || { }

    if (this.listenOptions.key && !this.listenOptions.cert) {
      throw new Error('You must set cert option too if you use key option')
    }
    if (!this.listenOptions.key && this.listenOptions.cert) {
      throw new Error('You must set key option too if you use cert option')
    }

    if (!this.authenticator) {
      throw new Error('You must set authentication callback by app.auth()')
    }

    if (!this.listenOptions.server) {
      if (!this.listenOptions.port) this.listenOptions.port = 1337
      if (!this.listenOptions.host) this.listenOptions.host = '127.0.0.1'
    }

    var app = this
    var promise = Promise.resolve()

    if (this.listenOptions.server) {
      this.ws = new WebSocket.Server({ server: this.listenOptions.server })
    } else {
      var before = []
      if (this.listenOptions.key && !isPem(this.listenOptions.key)) {
        before.push(readFile(this.options.root, this.listenOptions.key))
      } else {
        before.push(Promise.resolve(this.listenOptions.key))
      }
      if (this.listenOptions.cert && !isPem(this.listenOptions.cert)) {
        before.push(readFile(this.options.root, this.listenOptions.cert))
      } else {
        before.push(Promise.resolve(this.listenOptions.cert))
      }

      promise = promise
        .then(() => Promise.all(before))
        .then(keys => new Promise((resolve, reject) => {
          if (keys[0]) {
            app.http = https.createServer({ key: keys[0], cert: keys[1] })
          } else {
            app.http = http.createServer()
          }

          app.ws = new WebSocket.Server({ server: app.http })

          app.ws.on('error', reject)

          var opts = app.listenOptions
          app.http.listen(opts.port, opts.host, resolve)
        }))
    }

    app.unbind.push(() => promisify(done => {
      promise.then(() => {
        app.ws.close(() => {
          if (app.http) {
            app.http.close(done)
          } else {
            done()
          }
        })
      })
    }))

    return promise.then(() => {
      app.ws.on('connection', ws => {
        app.reporter('connect', app, remoteAddress(ws))
        app.lastClient += 1
        var client = new Client(app, new ServerConnection(ws), app.lastClient)
        app.clients[app.lastClient] = client
      })
    }).then(() => {
      app.reporter('listen', app)
    })
  },

  /**
   * Stop server and unbind all listeners.
   *
   * @return {Promise} Promise when all listeners will be removed.
   *
   * @example
   * afterEach(() => {
   *   testApp.destroy()
   * })
   */
  destroy: function destroy () {
    this.destroing = true
    this.reporter('destroy', this)
    return Promise.all(this.unbind.map(i => i()))
  },

  /**
   * Load options from command-line arguments and/or environment
   *
   * @param {object} process Current process object.
   * @param {object} defaults Default options.
   * @return {object} Parsed options object.
   *
   * @example
   * app.listen(app.loadOptions(process, { port: 31337 }))
   */
  loadOptions: function loadOptions (process, defaults) {
    defaults = defaults || { }

    var argv = yargs.parse(process.argv)
    var env = process.env

    return {
      host: argv.h || env.LOGUX_HOST || defaults.host,
      port: parseInt(argv.p || env.LOGUX_PORT || defaults.port, 10),
      cert: argv.c || env.LOGUX_CERT || defaults.cert,
      key: argv.k || env.LOGUX_KEY || defaults.key
    }
  },

  /**
   * Define action type’s callbacks.
   *
   * @param {string} name The action’s type.
   * @param {object} callbacks Callbacks for actions with this type.
   * @param {authorizer} callback.access Check does user can do this action.
   * @param {processor} callback.process Action business logic.
   *
   * @return {undefined}
   *
   * @example
   * app.type('CHANGE_NAME', {
   *   access (action, meta, user) {
   *     return Promise.resolve(action.user === user.id)
   *   },
   *   process (action, meta) {
   *     if (isFirstOlder(lastNameChange(action.user), meta)) {
   *       return db.changeUserName({ id: action.user, name: action.name })
   *     }
   *   }
   * })
   */
  type: function type (name, callbacks) {
    if (this.actions[name]) {
      throw new Error(`Action type ${ name } was already defined`)
    }
    if (!callbacks || !callbacks.access) {
      throw new Error(`Action type ${ name } must have access callback`)
    }
    if (!callbacks.process) {
      throw new Error(`Action type ${ name } must have process callback`)
    }
    this.actions[name] = callbacks
  }

}

module.exports = BaseServer

/**
 * @callback authenticator
 * @param {string} id User ID.
 * @param {any} credentials The client credentials.
 * @param {Client} client Client object.
 * @return {Promise} Promise with `false` or user data.
 */

/**
 * @callback authorizer
 * @param {Action} action The action data.
 * @param {Meta} action The action metadata.
 * @param {Client} client The client object.
 * @return {Promise} Promise with `true` if client are allowed
 *                   to use this action.
 */

/**
 * @callback processor
 * @param {Action} action The action data.
 * @param {Meta} action The action metadata.
 * @param {Client} client The client object.
 * @return {Promise|undefined} Promise when processing will be finished.
 */
<|endoftext|>


<commit_before>/*
    Copyright (c) 2015, SerGIS Project Contributors. All rights reserved.
    Use of this source code is governed by the MIT License, which can be found
    in the LICENSE.txt file.
*/

// node modules
var fs = require("fs"),
    path = require("path");

// our modules
var config = require("../../config"),
    writer = require("../writer.js");

// test auth tokens module
var TEST_AUTH_TOKENS = require("../../TEST_AUTH_TOKENS");
// test content components module
var TEST_CONTENT_COMPONENTS = require("../../TEST_CONTENT_COMPONENTS");
// test games module
var TEST_GAMES = require("../../TEST_GAMES");
// test users module
var TEST_USERS = require("../../TEST_USERS");

/**
 * Initialize the handler for connections to the "/game" socket.
 * This is called each time a new connection is made to the "/game" socket.
 *
 * @param socket - The Socket instance.
 * @param {Function} next - The function to call once we have initialized the
 *        socket on our end.
 */
module.exports = function (socket, next) {
    /*
    The client will send a "ready" event once it's all loaded up.
    data: {
        gameID: string
        authToken: string
    }
    callback(error message or null, initial game state)
    */
    socket.on("ready", function (data, callback) {
        var gameID = data.gameID,
            authToken = data.authToken;

        // Check auth token
        if (!TEST_AUTH_TOKENS.hasOwnProperty(authToken)) {
            // Invalid auth token!
            callback("Invalid auth token.");
            return;
        }

        // Get user from auth token
        var user = TEST_USERS[TEST_AUTH_TOKENS[authToken].userID];

        // Check game ID
        if (!TEST_GAMES.hasOwnProperty(gameID)) {
            // Invalid game ID!
            callback("Invalid game ID.");
            return;
        }

        // Get game from game ID
        var game = TEST_GAMES[gameID];

        // All is good; make GameSocket
        new GameSocket(socket, game, user, callback);
    });

    // Everything's initialized for us; move on!
    next();
};

///////////////////////////////////////////////////////////////////////////////
// Writer for Content Component templates
var contentComponentTemplateWriter = new writer.Writer(config.CONTENT_COMPONENTS_TEMPLATES_DIR);

function getContentComponent(id, callback) {
    id = Number(id);
    if (isNaN(id) || !id || !TEST_CONTENT_COMPONENTS.hasOwnProperty(id)) {
        // "Bad Request"
        callback(new Error("Invalid control ID."));
        //writer.writeError(res, 400, "Invalid control ID.");
        return;
    }

    var contentComponent = TEST_CONTENT_COMPONENTS[id];
    contentComponentTemplateWriter.render(contentComponent.type + ".html", contentComponent.vars || {}, function (err, data) {
        if (err) {
            console.log("Error rendering Content Component template:", err);
            callback(new Error("Error rendering Content Component template."));
            // "Internal Server Error"
            //writer.writeError(res, 500, "Error rendering Content Component template.");
            return;
        }

        callback(null, data);
    });
}

// Documentation for the callback functions to send a reply back to the client:
/**
 * A callback function to call in reply to an event sent by the client.
 * @callback GameSocket~requestCallback
 * @param {?string} err - An error message, or null if there was no error.
 * @param {*} [response] - Response data, if there was no error.
 */

/**
 * Class representing a socket connection with a specific game and user.
 * @class
 * @constructor
 *
 * @param socket - The Socket.IO socket connection to the client.
 * @param {object} game - The game data from the database.
 * @param {object} user - The user data from the database.
 * @param {GameSocket~requestCallback} initialCallback - The callback to give
 *        the client the initial game state.
 */
function GameSocket(socket, game, user, initialCallback) {
    this.socket = socket;
    this.game = game;
    this.user = user;

    // Check user object
    if (!this.user.games) this.user.games = {};
    if (!this.user.games[this.game.name]) this.user.games[this.game.name] = {};

    // Make shortcut for user.games[game.name]
    this.userGame = this.user.games[this.game.name];

    // Check userGame.userVars
    if (!this.userGame.userVars) this.userGame.userVars = {};

    // Check userGame.currentGameStateIndex
    if (typeof this.userGame.currentGameStateIndex != "number") {
        this.userGame.currentGameStateIndex = this.game.initialGameStateIndex;
    }

    // Set up socket handlers
    this.socket.on("getUserVar", this.handler_getUserVar.bind(this));
    this.socket.on("setUserVar", this.handler_setUserVar.bind(this));

    // Get dat client started
    initialCallback(null, this.game.gameStates[this.userGame.currentGameStateIndex].contentComponents);
}

/**
 * Handler for client socket "getUserVar" event.
 * Called by the client to get the value of a user variable.
 *
 * @param {object} data - name (string): the name of the variable to get.
 * @param {GameSocket~requestCallback} callback
 */
GameSocket.prototype.handler_getUserVar = function (data, callback) {
    if (!data || !data.name) {
        callback("Invalid data.");
    } else if (!this.userGame.userVars.hasOwnProperty(data.name)) {
        callback("Invalid user variable name.");
    } else {
        callback(null, this.userGame.userVars[name]);
    }
};

/**
 * Handler for client socket "setUserVar" event.
 * Called by the client to set a user variable.
 *
 * @param {object} data - name (string): the name of the variable to set.
 *                        value (string): the value of the variable to set.
 * @param {GameSocket~requestCallback} callback
 */
GameSocket.prototype.handler_setUserVar = function (data, callback) {
    this.userGame.userVars[data.name] = data.value;
    callback(null);
};

<commit_msg>Fixed up GameSocket handlers<commit_after>/*
    Copyright (c) 2015, SerGIS Project Contributors. All rights reserved.
    Use of this source code is governed by the MIT License, which can be found
    in the LICENSE.txt file.
*/

// node modules
var fs = require("fs"),
    path = require("path");

// our modules
var config = require("../../config"),
    writer = require("../writer.js");

// test auth tokens module
var TEST_AUTH_TOKENS = require("../../TEST_AUTH_TOKENS");
// test content components module
var TEST_CONTENT_COMPONENTS = require("../../TEST_CONTENT_COMPONENTS");
// test games module
var TEST_GAMES = require("../../TEST_GAMES");
// test users module
var TEST_USERS = require("../../TEST_USERS");

/**
 * Initialize the handler for connections to the "/game" socket.
 * This is called each time a new connection is made to the "/game" socket.
 *
 * @param socket - The Socket instance.
 * @param {Function} next - The function to call once we have initialized the
 *        socket on our end.
 */
module.exports = function (socket, next) {
    /*
    The client will send a "ready" event once it's all loaded up.
    data: {
        gameID: string
        authToken: string
    }
    callback(error message or null, initial game state)
    */
    socket.on("ready", function (data, callback) {
        var gameID = data.gameID,
            authToken = data.authToken;

        // Check auth token
        if (!TEST_AUTH_TOKENS.hasOwnProperty(authToken)) {
            // Invalid auth token!
            callback("Invalid auth token.");
            return;
        }

        // Get user from auth token
        var user = TEST_USERS[TEST_AUTH_TOKENS[authToken].userID];

        // Check game ID
        if (!TEST_GAMES.hasOwnProperty(gameID)) {
            // Invalid game ID!
            callback("Invalid game ID.");
            return;
        }

        // Get game from game ID
        var game = TEST_GAMES[gameID];

        // All is good; make GameSocket
        new GameSocket(socket, game, user, callback);
    });

    // Everything's initialized for us; move on!
    next();
};

///////////////////////////////////////////////////////////////////////////////
// Writer for Content Component templates
var contentComponentTemplateWriter = new writer.Writer(config.CONTENT_COMPONENTS_TEMPLATES_DIR);

function getContentComponent(id, callback) {
    id = Number(id);
    if (isNaN(id) || !id || !TEST_CONTENT_COMPONENTS.hasOwnProperty(id)) {
        // "Bad Request"
        callback(new Error("Invalid control ID."));
        //writer.writeError(res, 400, "Invalid control ID.");
        return;
    }

    var contentComponent = TEST_CONTENT_COMPONENTS[id];
    contentComponentTemplateWriter.render(contentComponent.type + ".html", contentComponent.vars || {}, function (err, data) {
        if (err) {
            console.log("Error rendering Content Component template:", err);
            callback(new Error("Error rendering Content Component template."));
            // "Internal Server Error"
            //writer.writeError(res, 500, "Error rendering Content Component template.");
            return;
        }

        callback(null, data);
    });
}

// Documentation for the callback functions to send a reply back to the client:
/**
 * A callback function to call in reply to an event sent by the client.
 * @callback GameSocket~requestCallback
 * @param {?string} err - An error message, or null if there was no error.
 * @param {*} [response] - Response data, if there was no error.
 */

/**
 * Class representing a socket connection with a specific game and user.
 * @class
 *
 * @param socket - The Socket.IO socket connection to the client.
 * @param {object} game - The game data from the database.
 * @param {object} user - The user data from the database.
 * @param {GameSocket~requestCallback} initialCallback - The callback to give
 *        the client the initial game state.
 */
function GameSocket(socket, game, user, initialCallback) {
    this.socket = socket;
    this.game = game;
    this.user = user;

    // Check user object
    if (!this.user.games) this.user.games = {};
    if (!this.user.games[this.game.name]) this.user.games[this.game.name] = {};

    // Make shortcut for user.games[game.name]
    this.userGame = this.user.games[this.game.name];

    // Check userGame.userVars
    if (!this.userGame.userVars) this.userGame.userVars = {};

    // Check userGame.currentGameStateIndex
    if (typeof this.userGame.currentGameStateIndex != "number") {
        this.userGame.currentGameStateIndex = this.game.initialGameStateIndex;
    }

    // Set up socket handlers (getUserVar, setUserVar)
    for (var eventName in GameSocket.handlers) {
        this.socket.on(eventName, GameSocket.handlers[eventName].bind(this));
    }

    // Get dat client started
    initialCallback(null, this.game.gameStates[this.userGame.currentGameStateIndex].contentComponents);
}

/**
 * Handlers for client socket events.
 * Each is called with 2 parameters: `data` and `callback` (both specified by
 * the client).
 * The `this` value in each function when it is called is the current GameSocket
 * instance.
 *
 * @type Array.<Function>
 */
GameSocket.handlers = {
    /**
     * Handler for client socket "getUserVar" event.
     * Called by the client to get the value of a user variable.
     *
     * @this GameSocket
     * @param {object} data - name (string): the name of the variable to get.
     * @param {GameSocket~requestCallback} callback
     */
    getUserVar: function (data, callback) {
        if (!data || !data.name) {
            callback("Invalid data.");
        } else if (!this.userGame.userVars.hasOwnProperty(data.name)) {
            callback("Invalid user variable name.");
        } else {
            callback(null, this.userGame.userVars[name]);
        }
    },

    /**
     * Handler for client socket "setUserVar" event.
     * Called by the client to set a user variable.
     *
     * @this GameSocket
     * @param {object} data - name (string): the name of the variable to set.
     *                        value (string): the value of the variable to set.
     * @param {GameSocket~requestCallback} callback
     */
    setUserVar: function (data, callback) {
        this.userGame.userVars[data.name] = data.value;
        callback(null);
    }
};
<|endoftext|>


<commit_before><commit_msg>Created showCard function<commit_after>function showCard() {
  let card1 = Math.floor(Math.random()*8 + 1); // random visar en bild av 8
	let img=document.getElementById("card1");
		img.src="images/"+card1+".png";
}
<|endoftext|>


<commit_before>// Main pages

module.exports = function(app) {
	// The greeting page is the login page

	app.get('/', function(req, res) {
		res.render('main', {title: 'Welcome to GEE'});
	});

	// The user clicked on "send feedback".  This will take him to a page
	// where he can send us feedback -- currently we are not displaying this
	// on the login page, so ATM the user must be logged in to send feedback
	// but no dependency, we can put this on the login page

	app.get('/send_feedback', function(req, res) {
		res.render('main_feedback', {title: 'Feedback'});
	});
}<commit_msg>Experimenting with redirecting based on req.session.user being set. #7<commit_after>// Main pages

module.exports = function(app) {
	// The greeting page is the login page

	app.get('/', function(req, res) {
		if (req.session) {
			if (req.session.user) {
				res.redirect('/logged_in');
			} else {
				res.render('main', {title: 'Welcome to GEE'});
			}
		} else {
			res.render('main', {title: 'Welcome to GEE'});
		}
	});

	// The user clicked on "send feedback".  This will take him to a page
	// where he can send us feedback -- currently we are not displaying this
	// on the login page, so ATM the user must be logged in to send feedback
	// but no dependency, we can put this on the login page

	app.get('/send_feedback', function(req, res) {
		res.render('main_feedback', {title: 'Feedback'});
	});
}<|endoftext|>