import java.lang.Math;


import java.util.HashMap;
import java.util.Map;

public class Light {
    boolean on;
    short red;
    short green;
    short blue;
    short effect;

    /*  ANSI effects
        n	Name	Note
        0	Reset or normal	All attributes off
        1	Bold or increased intensity	As with faint, the color change is a PC (SCO / CGA) invention.[38][better source needed]
        2	Faint, decreased intensity, or dim	May be implemented as a light font weight like bold.[39]
        3	Italic	Not widely supported. Sometimes treated as inverse or blink.[38]
        4	Underline	Style extensions exist for Kitty, VTE, mintty and iTerm2.[40][41]
        5	Slow blink	Sets blinking to less than 150 times per minute
        6	Rapid blink	MS-DOS ANSI.SYS, 150+ per minute; not widely supported
        7	Reverse video or invert	Swap foreground and background colors; inconsistent emulation[42]
        8	Conceal or hide	Not widely supported.
        9	Crossed-out, or strike	Characters legible but marked as if for deletion. Not supported in Terminal.app
     */
    private final Map<Short, String> EFFECT = new HashMap<>();
    {
        // Map<"separator", not_used>
        EFFECT.put((short) 0, "Normal");
        EFFECT.put((short) 1, "Bold");
        EFFECT.put((short) 2, "Faint");
        EFFECT.put((short) 3, "Italic");
        EFFECT.put((short) 4, "Underline");
        EFFECT.put((short) 5, "Slow Blink");
        EFFECT.put((short) 6, "Fast Blink");
        EFFECT.put((short) 7, "Reverse");
        EFFECT.put((short) 8, "Conceal");
        EFFECT.put((short) 9, "Crossed_out");
    }

    /* Assign random colors and effects */
    public Light() {
        int maxColor = 255;
        int effect = 9;
        this.red = (short) (Math.random()*(maxColor+1));
        this.green = (short) (Math.random()*(maxColor+1));
        this.blue = (short) (Math.random()*(maxColor+1));
        this.effect = (short) (Math.random()*(effect+1));
    }

    public String getEffectTitle() {
        return EFFECT.get(this.effect);
    }

    public String getRGB() {
        return ( "#" +
         String.format("%02X", this.red) +
         String.format("%02X", this.green) + 
         String.format("%02X", this.blue) 
         );
    }

    /* toString output as key/values */
    public String toString() {
        return( "{" + 
            "\"red\": " + red + "," +
            "\"green\": " +  green + "," + 
            "\"blue\": " + blue + "," +
            "\"effect\": " + "\"" + EFFECT.get(effect) + "\"" +
            "}" );
    }

    public boolean isOn() {
        return on;
    }

    public void setOn(boolean on) {
        this.on = on;
    }

    public short getRed() {
        return red;
    }

    public short getGreen() {
        return green;
    }

    public short getBlue() {
        return blue;
    }

    public short getEffect() {
        return effect;
    }

    static public void main(String[] args) {
        // create and display LightBoard
        Light light = new Light();
        System.out.println(light);  // use toString() method
    }
    

}
Light.main(null);


public class LightBoard {
    private Light[][] lights;

    /* Initialize LightBoard and Lights */
    public LightBoard(int numRows, int numCols) {
        this.lights = new Light[numRows][numCols];
        // 2D array nested loops, used for initialization
        for (int row = 0; row < numRows; row++) {
            for (int col = 0; col < numCols; col++) {
                lights[row][col] = new Light();  // each cell needs to be constructed
            }
        }
    }

    /* Output is intended for API key/values */
    public String toString() { 
        String outString = "[";
        // 2D array nested loops, used for reference
        for (int row = 0; row < lights.length; row++) {
            for (int col = 0; col < lights[row].length; col++) {
                outString += 
                // data
                "{" + 
                "\"row\": " + row + "," +
                "\"column\": " + col + "," +
                "\"light\": " + lights[row][col] +   // extract toString data
                "}," ;
            }
        }
        // remove last comma, newline, add square bracket, reset color
        outString = outString.substring(0,outString.length() - 1) + "]";
		return outString;
    }

    /* Output is intended for Terminal, effects added to output */
    public String toTerminal() { 
        String outString = "[";
        // 2D array nested loops, used for reference
        for (int row = 0; row < lights.length; row++) {
            for (int col = 0; col < lights[row].length; col++) {
                outString += 
                // reset
                "\033[m" +
                
                // color
                "\033[38;2;" + 
                lights[row][col].getRed() + ";" +  // set color using getters
                lights[row][col].getGreen() + ";" +
                lights[row][col].getBlue() + ";" +
                lights[row][col].getEffect() + "m" +
                // data, extract custom getters
                "{" +
                "\"" + "RGB\": " + "\"" + lights[row][col].getRGB() + "\"" +
                "," +
                "\"" + "Effect\": " + "\"" + lights[row][col].getEffectTitle() + "\"" +
                "}," +
                // newline
                "\n" ;
            }
        }
        // remove last comma, newline, add square bracket, reset color
        outString = outString.substring(0,outString.length() - 2) + "\033[m" + "]";
		return outString;
    }

    /* Output is intended for Terminal, draws color palette */
    public String toColorPalette() {
        // block sizes
        final int ROWS = 5;
        final int COLS = 10;

        // Build large string for entire color palette
        String outString = "";
        // find each row
        for (int row = 0; row < lights.length; row++) {
            // repeat each row for block size
            for (int i = 0; i < ROWS; i++) {
                // find each column
                for (int col = 0; col < lights[row].length; col++) {
                    // repeat each column for block size
                    for (int j = 0; j < COLS; j++) {
                        // print single character, except at midpoint print color code
                        String c = (i == (int) (ROWS / 2) && j == (int) (COLS / 2) ) 
                            ? lights[row][col].getRGB()
                            : (j == (int) (COLS / 2))  // nested ternary
                            ? " ".repeat(lights[row][col].getRGB().length())
                            : " ";

                        outString += 
                        // reset
                        "\033[m" +
                        
                        // color
                        "\033[38;2;" + 
                        lights[row][col].getRed() + ";" +
                        lights[row][col].getGreen() + ";" +
                        lights[row][col].getBlue() + ";" +
                        "7m" +

                        // color code or blank character
                        c +

                        // reset
                        "\033[m";
                    }
                }
                outString += "\n";
            }
        }
        // remove last comma, newline, add square bracket, reset color
        outString += "\033[m";
		return outString;
    }
    
    static public void main(String[] args) {
        // create and display LightBoard
        LightBoard lightBoard = new LightBoard(5, 5);
        System.out.println(lightBoard);  // use toString() method
        System.out.println(lightBoard.toTerminal());
        System.out.println(lightBoard.toColorPalette());
    }
}


public class LightBoard { 
    /** The lights on the board, where true represents on and false represents off. 
     */ 
    private boolean[][] lights; 
    /** Constructs a LightBoard object having numRows rows and numCols columns. 
     * Precondition: numRows > 0, numCols > 0 
     * Postcondition: each light has a 40% probability of being set to on. 
     */ 
    public LightBoard(int numRows, int numCols){
         /* to be implemented in part (a) */
        // initialize the 2D array
        lights = new boolean[numRows][numCols];

        // Using two enhanced for loops to iterate through the 2D array
        for (int i = 0; i < lights.length; i++) {
            for (int j = 0; j < lights[i].length; j++){
                // use math.random to generate a random number, less than 0.4, to determine if the light is on or off
                if (Math.random() < 0.4){
                    lights[i][j] = true;
                }
                else{
                    lights[i][j] = false;
                }
            }
        }

     }
    /** Evaluates a light in row index row and column index col and returns a status 
     * as described in part (b).
     * Precondition: row and col are valid indexes in lights.
     */
    public boolean evaluateLight(int row, int col)
    { /* to be implemented in part (b) */ 

        // CHECK IF LIGHT IS ON
        if (lights[row][col] == true) {
            // return false if the number of lights in its column are even
            int counter = 0;

            // iterate through every row and check for value of the column, if true increment counter
           for (int i = 0; i < lights.length; i++){
               if (lights[i][col] == true){
                   counter++;
               }
           }

           // check if counter is even or odd
           if (counter % 2 == 0){
               return false;
           }
           else{
               return true;
           }

        }
        // If light is off
        else {
            int counter = 0;
            // Count number of lights in the column
            for (int i = 0; i < lights.length; i++){
                if (lights[i][col] == true){
                    counter++;
                }
            }

            // return true if the number of lights in the column is divisible by 3
            if (counter % 3 == 0) {
                return true;
            }
            else {
                return false;
            }
        }
    }
    // There may be additional instance variables, constructors, and methods not shown. 
}

LightBoard lightBoard = new LightBoard(5, 5);
System.out.println(lightBoard);  // use toString() method


LightBoard a = new LightBoard(5,5);
System.out.println(a.evaluateLight(0,0));
System.out.println(a.evaluateLight(0,1));
System.out.println(a.evaluateLight(0,2));
{"red": 249,"green": 24,"blue": 154,"effect": "Italic"}
REPL.$JShell$13BI$LightBoard@24412e0d
false
false
true