JS: Prozentrechnung


  • Banned

    Hi, ich bin nicht so sattelfest in JavaScript, also weiß ich nicht genau, was falsch wäre...?

    In der Game-Loop wird immer wieder folgende Funktion aufgerufen, die neue Creeps anteilig spawnen soll...

    function spwanNewCreep(spawn, myTime) {
        var percent = [
            30, 30, 30, 10
        ];
        var count = [0, 0, 0, 0];
        var myCreeps = Game.creeps;
        for (var name in myCreeps) {
            var creep = Game.creeps[name];
            if (creep.memory.role == 'worker') {
                count[0]++;
            } else if (creep.memory.role == 'spawn') {
                count[1]++;
            } else if (creep.memory.role == 'build') {
                count[2]++;
            } else if (creep.memory.role == 'free') {
                count[3]++;
            }
        }
        var sum = myCreeps.length;
        var index = 0;
        for (var i = 0; i < count.length; i++) {
            var p1 = (100 * count[i] / sum) - percent[i];
            var p2 = (100 * count[index] / sum) - percent[index];
            if (p1 < p2) {
                index = i;
            }
        }
    
        if (index == 0) {
            var newName = 'Worker' + myTime;
            // ...
    }
    

    Dabei soll es 30% worker, 30% spawn, 30% build und 10% free-Creeps geben...

    Ich hab in der Schleife bestimmt irgendetwas falsch gemacht, aber was könnte es sein?

    Vielen Dank, wer mal drüberschaut.

    Edit: Also der Index ist immer 0, obwohl es schon ganz viele worker-Creeps gibt...


  • Banned

    @EinNutzer0 sagte in JS: Prozentrechnung:

    var sum = myCreeps.length;

    Ohhh 😞 ich bin wirklich sehr dumm, denn sum war immer undefined, weil myCreeps kein Array, sondern ein Object ist...

    Demzufolge muss es heißen: var size = Object.keys(myCreeps).length;

    function spwanNewCreep(spawn, myTime) {
        var percent = [
            30, 30, 30, 10
        ];
        var count = [0, 0, 0, 0];
        var myCreeps = Game.creeps;
        for (var name in myCreeps) {
            var creep = Game.creeps[name];
            if (creep.memory.role == 'worker') {
                count[0]++;
            } else if (creep.memory.role == 'spawn') {
                count[1]++;
            } else if (creep.memory.role == 'build') {
                count[2]++;
            } else if (creep.memory.role == 'free') {
                count[3]++;
            }
        }
        var size = Object.keys(myCreeps).length;
        console.log(size);
        var index = 0;
        for (var i = 0; i < count.length; i++) {
            var p1 = (100 * count[i] / size) - percent[i];
            var p2 = (100 * count[index] / size) - percent[index];
            if (p1 < p2) {
                index = i;
            }
        }
    

    Jetzt spawnt auch der richtige Creep...

    Wer JavaScript erfand, der war ein Halunke! 😃



  • Ok, dein Problem scheint ja gelöst. Ich habe mir deinen Quelltext auch nicht vollständig angeguckt. Aber einen generellen Kommenar habe ich:

    Ich würde, wenn möglich, const für Variablendeklarationen/Definitionen benutzen. Wenn du ändern willst, dann let. Und var (was du überall nutzt) nur dann, wenn du wirklich das (zumindest für nicht js-Entwickler) seltsame Verhalten von var haben willst. Das hat aber mit deinem Problem nix zu tun und ist auch so ungefähr das einzige, was ich über js weiß 😉


  • Banned

    Danke, ja... vielleicht sollte ich wirklich alle var durch let ersetzen... Kenn mich damit kaum aus...

    @EinNutzer0 sagte in JS: Prozentrechnung:

    (100 * count[i] / size)

    das würde in einer "normalen" Programmiersprache ja schon als Ganzzahldivision schief gehen, aber nicht so in JS...


  • Banned

    Funktioniert alles super mit let. 😃

    Ich wag es mich eigentlich nicht zu fragen... aber was ist der Unterschied zwischen var und let?

    Und wenn ich so etwas schreibe: if (myArray.length) {, kann ich dann davon ausgehen, dass myArray existiert UND mindestens ein Element beinhaltet?


  • Mod

    @EinNutzer0 sagte in JS: Prozentrechnung:

    was ist der Unterschied zwischen var und let?

    Das kannst du buchstäblich so in jede Suchmaschine eintippen und bekommst eine gute Erklärung, die sogar ich verstanden habe, obwohl ich nicht einmal JS spreche…


  • Banned

    @EinNutzer0 sagte in JS: Prozentrechnung:

    var count = [0, 0, 0, 0];

    Das ist auch suboptimal, besser: let count = new Array(percent.length).fill(0);

    function spwanNewCreep(spawn, myTime) {
        let percent = [
            40, 25, 25, 10
        ];
        let count = new Array(percent.length).fill(0);
        let myCreeps = Game.creeps;
        for (let name in myCreeps) {
            let creep = Game.creeps[name];
            if (creep.memory.role == 'worker') {
                count[0]++;
            } else if (creep.memory.role == 'spawn') {
                count[1]++;
            } else if (creep.memory.role == 'build') {
                count[2]++;
            } else if (creep.memory.role == 'free') {
                count[3]++;
            }
        }
        let size = Object.keys(myCreeps).length;
        let index = 0;
        for (let i = 0; i < count.length; i++) {
            let p1 = (100 * count[i] / size) - percent[i];
            let p2 = (100 * count[index] / size) - percent[index];
            if (p1 < p2) {
                index = i;
            }
        }
    
        if (index == 0) {
            let newName = 'Worker' + myTime;
            if (spawn.spawnCreep([WORK, WORK, CARRY, MOVE], newName, { memory: { role: 'worker' } }) == OK) {
                console.log('Spawning new: ' + newName);
                spawn.room.visual.text(
                    '🛠️' + newName,
                    spawn.pos.x + 1,
                    spawn.pos.y,
                    { align: 'left', opacity: 0.8 });
            }
        } else if (index == 1) {
            let newName = 'Spawn' + myTime;
            if (spawn.spawnCreep([WORK, CARRY, MOVE], newName, { memory: { role: 'spawn' } }) == OK) {
                console.log('Spawning new: ' + newName);
                spawn.room.visual.text(
                    '🛠️' + newName,
                    spawn.pos.x + 1,
                    spawn.pos.y,
                    { align: 'left', opacity: 0.8 });
            }
        } else if (index == 2) {
            let newName = 'Build' + myTime;
            if (spawn.spawnCreep([WORK, CARRY, MOVE], newName, { memory: { role: 'build' } }) == OK) {
                console.log('Spawning new: ' + newName);
                spawn.room.visual.text(
                    '🛠️' + newName,
                    spawn.pos.x + 1,
                    spawn.pos.y,
                    { align: 'left', opacity: 0.8 });
            }
        } else if (index == 3) {
            let newName = 'Free' + myTime;
            if (spawn.spawnCreep([WORK, CARRY, MOVE], newName, { memory: { role: 'free' } }) == OK) {
                console.log('Spawning new: ' + newName);
                spawn.room.visual.text(
                    '🛠️' + newName,
                    spawn.pos.x + 1,
                    spawn.pos.y,
                    { align: 'left', opacity: 0.8 });
            }
        }
    }
    

    Falls jemand zufällig sieht, wie es "besser" ginge... immer her damit. 😃



  • @EinNutzer0 Du hast sehr viele Code Dopplungen. Ich würde davon ausgehen, dass sich das besser generalisieren lässt.


  • Banned

    Wäre eine Klasse und ein Array mit Instanzen dieser Klasse sinnvoll? Oder meidet man in JS Klassen?



  • Eine zweite Funktion würde hier schon reichen.


  • Banned

    Ich sage euch mal, was ich vor habe...

    Wie man sieht, hat jeder Creep ein Memory-Objekt, in das bis zu 2MB an Daten gespeichert werden können. Ich weiß noch nicht genau, wie dieses funktioniert... Hier ist eine Beschreibung dazu https://docs.screeps.com/global-objects.html#Memory-object .

    Wenn ich das richtig verstehe, können die "primitiven" Typen (int, float, string,...) an das Memory-Objekt gebunden werden, jedoch keine Klassen-Objekte...

    Ich möchte gerne eine Superklasse MyAction haben und dann unterschiedliche, von dieser Klasse abgeleiteten Klassen, die alle eine runAction(creep) Funktion beinhalten. Ein konkretes, abgeleitetes Klassen-Objekt möchte ich an jeden Creep heften... Dafür möchte ich das konkrete Objekt mit JSON.stringify zu einem string serialisieren und hinterher mit parse wiederherstellen, um dann runAction aufrufen zu können. So weit der Plan...

    a) Gibt es in JS Superklassen mit abstrakten Funktionen, die alle Kinderklassen implementieren müssen? Sprich:

    let meinHaustier1 = new Fisch();
    let meinHaustier2 = new Hamster();
    let arr = [meinHaustier1, meinHaustier2];
    console.log(arr[0].gibLaut(), arr[1].gibLaut());
    

    Geht das?

    b) Wie kann ich das Array arr mit den Objekten mit JSON.stringify serialisieren/schreiben/speichern?

    Ich hab schon gelesen, dass JS nicht streng typisiert ist, das heißt, Arrays unterschiedlicher Typen sind möglich... aber das möchte ich ja eigentlich vermeiden.

    Danke, wer bis hierhin gelesen hat. 😃


Log in to reply