Small supply chain simulation code (I'm learning Java basics)

Things that are not directly connected with Factorio.
Post Reply
Mendel
Filter Inserter
Filter Inserter
Posts: 265
Joined: Mon Aug 17, 2015 1:51 pm
Contact:

Small supply chain simulation code (I'm learning Java basics)

Post by Mendel »

So I took a course on Java... once the course started talking about Suppliers, I immediately started thinking about supply chains and Factorio of course. So I started this little side project to see how those could be used to simulate a small part of a supply chain. I go from iron and copper ores to the end product of inserter in a really simplified chain.

It's just a bunch of text really but if you are interested in Java coding and know enough to copy paste and compile this then go ahead! This could be expanded a lot of course and maybe made interactive if/when I have time. Also you can obviously consider this open source in case anyone wants to continue to make a Factorio text adventure :)

You may adjust static long delay variable to your liking if it feels like the output takes too long. I used Intellij idea to code this but it might/should work on any java ide obviously.

Mainly this might be sort of interesting if anyone else here happens to also be learning java. Or maybe not. It's super basic but here we go!


Code: Select all

import java.util.Stack;
import java.util.function.Supplier;
 
public class Main {
    public static final String ANSI_NORMAL = "\u001B[0m";
    public static final String ANSI_YELLOW = "\u001B[33m";
    public static final String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_RED = "\u001B[31m";
    static Supplier<IronOre> ironMine = IronOre::new;
    static Supplier<IronPlate> ironSmelter = () -> new IronPlate(ironMine.get());
    static Stack<IronPlate> ironPlateStack = new Stack<>();
    static Supplier<IronGear> ironGearFactory = () -> new IronGear(ironPlateStack.pop());
    static Stack<IronGear> ironGearStack = new Stack<>();
    static Stack<CopperPlate> copperPlateStack = new Stack<>();
    static Stack<CopperWire> copperWireStack = new Stack<>();
    static Supplier<CopperOre> CopperMine = CopperOre::new;
    static Supplier<CopperPlate> copperPlateSmelter = () -> new CopperPlate(CopperMine.get());
    static Supplier<CopperWire> copperWireFactory = () -> new CopperWire(copperPlateStack.pop());
    static Supplier<ElectronicCircuit> electronicCircuitFactory = () ->
            new ElectronicCircuit(copperWireStack.pop(), copperWireStack.pop(),
                    copperWireStack.pop(), ironPlateStack.pop());
    static Stack<ElectronicCircuit> circuitStack = new Stack<>();
    static Supplier<Inserter> inserterFactory = () ->
            new Inserter(circuitStack.pop(), ironGearStack.pop(), ironPlateStack.pop());
    static Stack<Inserter> inserterStack = new Stack<>();
 
    static long delay=250;
    public static void main(String[] args) {
 
 
        Stack<Inserter> localInserterStack = produceInserters(42);
 
        Stack<Inserter> playerInserterStack = new Stack<>();
        int carryCapacity = 2;
        System.out.println(ANSI_NORMAL + "Bot is carrying "
                + ANSI_YELLOW + carryCapacity + " inserters" + ANSI_NORMAL
                + " from stack to player");
        try {
            Thread.sleep(delay*8);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        for (int i = 0; i < carryCapacity; i++) {
            playerInserterStack.push(localInserterStack.pop());
        }
        localInserterStack = produceInserters(10);
        System.out.println(ANSI_NORMAL + "Leftover iron plates: "
                + ironPlateStack.size());
        System.out.println(ANSI_RED + "Leftover copper plates: "
                + copperPlateStack.size());
 
        System.out.println(ANSI_YELLOW + "Final amount of inserters in stack: "
                + inserterStack.size());
        System.out.println("Player has: " + playerInserterStack.size() + " inserters");
 
    }
 
    private static Stack<Inserter> produceInserters(int amount) {
        int count = 0;
        int count2 = 0;
        for (int i = 0; i < amount; i++) {
            for (int j = 0; j < 3; j++) {
                copperPlateStack.push(copperPlateSmelter.get());
                count++;
                System.out.println(ANSI_RED + "Total of " + count
                        + " copper plates smelted on this run");
                copperWireStack.push(copperWireFactory.get());
                System.out.println(ANSI_RED + "Total of " + count
                        + " copper wires produced on this run");
                ironPlateStack.push(ironSmelter.get());
                System.out.println(ANSI_NORMAL + "Total of " + count
                        + " iron plates smelted on this run");
                try {
                    Thread.sleep(delay);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            }
            count2++;
            ironGearStack.push(ironGearFactory.get());
            System.out.println(ANSI_NORMAL + "Total of " + count2
                    + " iron gears produced on this run");
            circuitStack.push(electronicCircuitFactory.get());
            System.out.println(ANSI_GREEN + "Total of " + count2
                    + " electronic circuits produced on this run");
            inserterStack.push(inserterFactory.get());
            System.out.println(ANSI_YELLOW + "Total of " + count2
                    + " inserters produced on this run");
            System.out.println("");
            System.out.println(ANSI_NORMAL + (amount-count2)+" more"
                    +ANSI_YELLOW+" inserters"+ANSI_NORMAL+" in production queue ");
            System.out.println("");
            try {
                Thread.sleep(delay*2);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
 
        }
        Stack[] stacks =
                {copperPlateStack, copperWireStack, ironPlateStack, ironGearStack, circuitStack};
 
        for (Stack stack : stacks) {
            if (stack.size() > 0) {
                System.out.println("Leftovers: " + stack.size());
            }
 
        }
 
 
        return inserterStack;
    }
 
}
 
class CopperOre {
    private int amount = 1;
    private String name = "Copper";
}
 
 
class CopperPlate {
    private CopperOre COResource;
 
    public CopperPlate(CopperOre COResource) {
        this.COResource = COResource;
    }
 
 
}
 
 
class CopperWire {
    private CopperPlate resource;
 
    public CopperWire(CopperPlate resource) {
        this.resource = resource;
    }
}
 
class ElectronicCircuit {
 
 
    private CopperWire resource;
    private CopperWire resource2;
    private CopperWire resource3;
    private IronPlate ironResource;
 
    public ElectronicCircuit(CopperWire resource, CopperWire resource2,
                             CopperWire resource3, IronPlate ironResource) {
        this.resource = resource;
        this.resource = resource2;
        this.resource = resource3;
        this.ironResource = ironResource;
    }
}
 
 
class Inserter {
    private ElectronicCircuit resource1;
    private IronGear resource2;
    private IronPlate resource3;
 
    public Inserter(ElectronicCircuit resource1, IronGear resource2, IronPlate resource3) {
        this.resource1 = resource1;
        this.resource2 = resource2;
        this.resource3 = resource3;
    }
}
 
 
class IronGear {
    private IronPlate resource;
 
    public IronGear(IronPlate resource) {
        this.resource = resource;
    }
}
 
 
class IronOre {
    private int amount = 1;
    private String name = "Iron";
}
 
 
class IronPlate {
    private IronOre resource;
 
    public IronPlate(IronOre resource) {
        this.resource = resource;
    }
}


A little humble question for better coders: In this simulation, to make an electronic circuit: 3 copper wires and one iron plate are required.

I have found this clumsy way of using 3 copper wires as 1 argument each in the constructor of ElectronicCircuit class. Ideally I would like to have only 2 arguments but to still have the requirement that one of the arguments somehow specifies that there is a required amount of 3 of the wires for the first argument (and the other argument is satisfied with just one iron plate).

How would I go about making that kind of thing more elegant? (other than rewriting the whole thing obviously) or is that even possible?


to do:
-more stuff
-text menu that lets player decide what to produce, check amounts of resources, set up factories and what not.

Amarula
Filter Inserter
Filter Inserter
Posts: 511
Joined: Fri Apr 27, 2018 1:29 pm
Contact:

Re: Small supply chain simulation code (I'm learning Java basics)

Post by Amarula »

Oh this looks like fun!

You already have the concept of stacks of resources. What if you passed the stack to each constructor, and let the constructor pop however many it needs, instead of popping the stack to get the resource to pass to the next constructor? So for instance instead of "new IronGear(ironPlateStack.pop())" you would have "new IronGear(ironPlateStack)" and the constructor would be "public IronGear(IronPlateStack resourceStack) { this.resource = resourceStack.pop(); }

Thanks for sharing!
My own personal Factorio super-power - running out of power.

Mendel
Filter Inserter
Filter Inserter
Posts: 265
Joined: Mon Aug 17, 2015 1:51 pm
Contact:

Re: Small supply chain simulation code (I'm learning Java basics)

Post by Mendel »

That seems like a good idea! Thanks!
I have to crunch to finish the course before the end of the year but I will return to this side project asap :)

Honktown
Smart Inserter
Smart Inserter
Posts: 1025
Joined: Thu Oct 03, 2019 7:10 am
Contact:

Re: Small supply chain simulation code (I'm learning Java basics)

Post by Honktown »

Have you thought about making it more like the game, but super-simplified?

ingredients are an item stack (vector/linked-list/whatever), the items only need name and amount (generic data)

They get passed to an assembler object which has a recipe (subtracts from incoming stacks if all match requirements, adds to output item stack)

when "finished", assembler outputs an item stack which can be fed to another assembler (directly as argument) or a "handler" object which takes object1 and inputs it to object2 depending on what they are, so you could make a vector of ingredients, assembler, assembler.

For combining multiple outputs, you can keep track of which assemblers are finished, and loop through crafting "sets": if ingredients1->machine A->machine C stops because C needs more ingredients, move on to ingredients2->machine B->machine C, and since machine C is now satisfied, it can run, finishing the second set. When you get back to the first set, machine C has finished so that one doesn't need anything done, and all the "processing" has been done, so you can see what A, B, and C have in inventory or whatever.

etc.
I have mods! I guess!
Link

Post Reply

Return to “Off topic”