/* Let's see what AI can do for us today.
GitHub Copilot AI request:

Can you create an arduino uno r3 program
I have 6 buttons on pins 2 through 7, use INPUT_PULLUP mode.
I have 6 LEDs on pins 8 through 13.
use library thomasfredericks/Bounce2 for the buttons.
use millis() and do not call delay()
Add a global called Mode which as the possible ModeEnum enum values ModeBinaryCounter, ModeLarsonScanner, ModeRandomLight, ModeClickOnClickOff, ModeWhackAMole, ModeToggler
In setup call a function WaitForModeSelection which will wait for one of the buttons to be pushed and select the mode. Print the name of the mode from a name array and print "press reset button to start over"
In loop, based on the mode, call LoopBinaryCounter() LoopLarsonScanner() LoopRandomLight() LoopClickOnClickOff() LoopToggler() LoopWhackAMole()

In the LoopBinaryCounter function every 0.25 seconds output to the LEDs a binary count. use static variables for the interval and previousMillis
In the LoopLarsonScanner function, every 0.5 seconds output to the LEDs a larson scanner. use static variables for the interval and previousMillis and other variables
In the LoopRandomLight function, every 0.5 seconds output turn on a random LED and turn off the last LED. use static variables for the interval and previousMillis and other variables
In the LoopClickOnClickOff function, when a button is pushed, toggle the state of the corresponding LED. Keep track of how long each LED has been on and if greater than 10 seconds, turn it off
In the LoopToggler function toggle the 6 LEDs at the following rates in milliseconds 100, 250, 333, 1000, 1234, 5000
In the LoopWhackAMole function make a game that runs for 30 seconds where one light comes on and when a user pushes the corresponding button, then the light goes off and a point is added to TotalScore. Award two points if the button is pushed within 0.5 seconds. At the end of the game print the TotalScore to the Serial port. Use static variables for the interval and previousMillis

can you write an arduino program that drives a bi-directional led across two pins without a resistor. Toggle the LEDS using millis every second and use only digitalWrite LOW and pinmode INPUT_PULLUP.
Note: chatbot did not understand this technique, code for LedRotator was hand done
Note: this took about half of the time it would have taken me to write the code myself and the
      output code is clean and well done. 
      It would not have been as successful if I didn't already know how to code what
      I wanted it to do and how to proofread for mistakes. Learning to code is still
      a very worthwile part of it. Do not overdepend on AI

*/

const uint8_t photoresistorPin = A0;  // wokwi doesn't have photoresistor component, so used a potentiometer 
const uint8_t ledNoResistorPin1 = A2;  // Define LED pin 1
const uint8_t ledNoResistorPin2 = A3; // Define LED pin 2
const uint8_t ledNoResistorPin3 = A5;  // Define LED pin 3
const uint8_t ledNoResistorPin4 = A4; // Define LED pin 4

#include <Bounce2.h>   // thomasfredericks/Bounce2 library

enum ModeEnum {
  ModeBinaryCounter,
  ModeLarsonScanner,
  ModeRandomLight,
  ModeClickOnClickOff,
  ModeToggler,
  ModeWhackAMole,
  ModeCount // Helper to get the number of modes
};

const char* modeNames[ModeCount] = {
  "Binary Counter",
  "Larson Scanner",
  "Random Light",
  "Click On Click Off",
  "Toggler",
  "Whack A Mole"
};

ModeEnum currentMode;
const int buttonPins[] = {2, 3, 4, 5, 6, 7};
const int ledPins[] = {8, 9, 10, 11, 12, 13};
const int noResistorLedPins[] = { ledNoResistorPin1, ledNoResistorPin2, ledNoResistorPin3, ledNoResistorPin4 };
const int numButtons = 6;
const int numNoResistorLedPins = 4;

Bounce buttons[numButtons];

void setup() {
  Serial.begin(9600);

  // danger, these LEDs do not utilize a current limiting resistor, do not set digitalWrite to HIGH
  for (int i = 0; i < 4; i++)
  {
    pinMode(noResistorLedPins[i], OUTPUT);
    digitalWrite(noResistorLedPins[i], LOW);
  }

  for (int i = 0; i < numButtons; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP);
    buttons[i].attach(buttonPins[i]);
    buttons[i].interval(25); // Debounce interval
    pinMode(ledPins[i], OUTPUT);
    digitalWrite(ledPins[i], LOW);
  }

  WaitForModeSelection();
}

void loop() {
  switch (currentMode) {
    case ModeBinaryCounter:
      LoopBinaryCounter();
      break;
    case ModeLarsonScanner:
      LoopLarsonScanner();
      break;
    case ModeRandomLight:
      LoopRandomLight();
      break;
    case ModeClickOnClickOff:
      LoopClickOnClickOff();
      break;
    case ModeToggler:
      LoopToggler();
      break;
    case ModeWhackAMole:
      LoopWhackAMole();
      break;
    default:
      break;
  }
   LedRotator();
}

void WaitForModeSelection() {
  Serial.println("Select a mode by pressing a button:");
  while (true) {
    for (int i = 0; i < numButtons; i++) {
      buttons[i].update();
      if (buttons[i].fell()) {
        currentMode = static_cast<ModeEnum>(i);
        Serial.print("Selected Mode: ");
        Serial.println(modeNames[currentMode]);
        Serial.println("Press reset button to start over");
        return;
      }
    }
  }
}

void LoopBinaryCounter() {
  static unsigned long previousMillis = 0;
  static const unsigned long interval = 250; // 0.25 seconds
  static int counter = 0;

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    counter = (counter + 1) % 64; // 6 LEDs, so count from 0 to 63

    for (int i = 0; i < numButtons; i++) {
      digitalWrite(ledPins[i], (counter >> i) & 0x01);
    }
  }
}

void LoopLarsonScanner() {
  static unsigned long previousMillis = 0;
  static const unsigned long interval = 500; // 0.5 seconds
  static int position = 0;
  static int direction = 1;

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Turn off all LEDs
    for (int i = 0; i < numButtons; i++) {
      digitalWrite(ledPins[i], LOW);
    }

    // Turn on the current LED
    digitalWrite(ledPins[position], HIGH);

    // Update position
    position += direction;
    if (position == numButtons - 1 || position == 0) {
      direction = -direction; // Reverse direction at the ends
    }
  }
}

void LoopRandomLight() {
  static unsigned long previousMillis = 0;
  static const unsigned long interval = 500; // 0.5 seconds
  static int lastLed = -1;

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Turn off the last LED
    if (lastLed != -1) {
      digitalWrite(ledPins[lastLed], LOW);
    }

    // Turn on a random LED
    int randomLed = random(numButtons);
    digitalWrite(ledPins[randomLed], HIGH);

    // Update last LED
    lastLed = randomLed;
  }
}

void LoopClickOnClickOff() {
  static unsigned long ledOnTimes[numButtons] = {0, 0, 0, 0, 0, 0};

  unsigned long currentMillis = millis();
  for (int i = 0; i < numButtons; i++) {
    buttons[i].update();
    if (buttons[i].fell()) {
      // Toggle the state of the corresponding LED
      int ledState = digitalRead(ledPins[i]);
      digitalWrite(ledPins[i], !ledState);
      if (!ledState) {
        ledOnTimes[i] = currentMillis; // Record the time the LED was turned on
      }
    }

    // Turn off the LED if it has been on for more than 10 seconds
    if (digitalRead(ledPins[i]) == HIGH && (currentMillis - ledOnTimes[i] >= 10000)) {
      digitalWrite(ledPins[i], LOW);
    }
  }
}

void LoopToggler() {
  static unsigned long previousMillis[6] = {0, 0, 0, 0, 0, 0};
  static const unsigned long intervals[6] = {100, 250, 333, 1000, 1234, 5000};
  static bool ledStates[6] = {LOW, LOW, LOW, LOW, LOW, LOW};

  unsigned long currentMillis = millis();

  for (int i = 0; i < 6; i++) {
    if (currentMillis - previousMillis[i] >= intervals[i]) {
      previousMillis[i] = currentMillis;
      ledStates[i] = !ledStates[i];
      digitalWrite(ledPins[i], ledStates[i]);
    }
  }
}


void LoopWhackAMole() {
  static unsigned long previousMillis = 0;
  static const unsigned long interval = 1000; // 1 second for changing the LED
  static unsigned long gameStartMillis = 0;
  static int currentLed = -1;
  static int totalScore = 0;
  static bool gameRunning = false;
  static bool initialized = false;

  unsigned long currentMillis = millis();

  if (!initialized) {
    gameStartMillis = currentMillis;
    initialized = true;
    gameRunning = true;
    Serial.println("Whack-A-Mole game started!");
  }

  if(!gameRunning) return;

  if (currentMillis - gameStartMillis >= 30000L) { // 30 seconds game duration
    gameRunning = false;
    Serial.print(" Game Over! Total Score: ");
    Serial.println(totalScore);
    totalScore = 0; // Reset score for next game
    return;
  }

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Turn off the current LED
    if (currentLed != -1) {
      digitalWrite(ledPins[currentLed], LOW);
    }

    // Turn on a new random LED
    currentLed = random(numButtons);
    digitalWrite(ledPins[currentLed], HIGH);
  }

  for (int i = 0; i < numButtons; i++) {
    buttons[i].update();
    if (buttons[i].fell() && i == currentLed) {
      unsigned long reactionTime = currentMillis - previousMillis;
      if (reactionTime <= 500) {
        totalScore += 2; // Award 2 points if button is pressed within 0.5 seconds
        Serial.print("!");
      } else {
        totalScore += 1; // Award 1 point otherwise
        Serial.print("+");
      }
      digitalWrite(ledPins[currentLed], LOW); // Turn off the LED
      currentLed = -1; // Reset current LED
    }
  }
}



void LedRotator() {
  static unsigned long lastToggleTime = 0; // Static variable to hold last toggle time
  static int ledState = 0; // Static variable to hold the state of the LEDs
  static unsigned long photoresistorTimeInterval = 1000;
  unsigned long currentTime = millis(); // Get the current time
  
  // Check if 1 second has passed
  if (currentTime - lastToggleTime < photoresistorTimeInterval) return;

  lastToggleTime = currentTime; // Update the last toggle time
  photoresistorTimeInterval = map(analogRead(photoresistorPin), 0,1023,  100,2000);

  // Toggle the LED state
  // danger, these LEDs do not utilize a current limiting resistor, do not set digitalWrite to HIGH
  for (int i = 0; i < numNoResistorLedPins; i++)
  {
    pinMode(noResistorLedPins[i], OUTPUT);
    digitalWrite(noResistorLedPins[i], LOW);
  }
  // since no current limiting resistor, use the internal 10k pullup resistor (INPUT_PULLUP) 
  // instead of digitalWrite HIGH which would cause damage to pin/LED
  pinMode(noResistorLedPins[ledState], INPUT_PULLUP);
  ledState = (ledState + 1) % numNoResistorLedPins;
}
$abcdeabcde151015202530fghijfghij