/*

###### Airsoft/Paintball Domination Game ######

Description:

No space for the batteries, so that was a bad design.  Everything but the 6 LED lamps is powered
by a 5v USB battery bank.  The LED lamps are powered by an airsoft 11.1v lipo.

To start a game, just press and release the "admin" button (the yellow/orange middle one that
doesn't illuminate.  That immediately begins starts the game timer (which can be changed in the code).
The box blinks orange to indicate no team has held the point yet.

Blue team presses and releases the blue button and their time begins immediately, complete
with the blue flashing light.  Green button does the same.  

When the game timer runs out, the program looks at the two accrued times, and whichever
team has the most time, the box will rapidly blink that team's color LED lamps.

In the case of a tie, the box will rapidly blink the orange admin lights.  And, of course,


    The circuit:

      Arduino Uno R3.
      SunFounder IIC I2C 16x2.
      3 momentary push buttons (two illuminate).
      Three relays.
      Six LED lamps in appropriate colors.
      Translucent ammo can.


    Created 21 September 2023

      Modified 6 October 2023
        * added "Press Start"
        * LCD now shows HH:MM:SS
      
    By BearsoftME
    for Southern Aroostook Action Sports
    SAASMaine.com

Any questions or comments, please email the author: [email protected]
 
    Demo:  https://www.youtube.com/watch?v=ft3u3nQDFkM

    Partial Parts List:
    The board is ELEGOO UNO: https://www.amazon.com/gp/product/B01EWOE0UU/
    The display is a standard I2C: https://www.amazon.com/gp/product/B019K5X53O/
    The relays:  https://www.amazon.com/gp/product/B07BVXT1ZK/
    The buttons: https://www.amazon.com/gp/product/B071CNX3CF/
    The LEDs... pick your colors:  https://www.amazon.com/gp/product/B07FXTGBBB/
    The box is a clear ammo can-style box from Walmart.. find it in home improvement.  

Instead of powering the LEDs via the relays with the 5v from the board, I used an airsoft 11.1v lipo.
I powered the ELEGOO with a USB power bank.  

I used a "breadboard" and jumper wires to build mine, as I was pressed for time, but I would HIGHLY
recommend getting a breakout board.  I'll be getting one this winter and rewiring my DOMBOX.  It'll
make better and stronger connections:  https://www.amazon.com/s?k=uno+breakout+board


*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // Initialize the LCD

const int orangeButtonPin = 2; // Orange button pin
const int blueButtonPin = 3;   // Blue team button pin
const int greenButtonPin = 4;   // Green team button pin
const int orangeRelayPin = 5;  // Orange relay pin
const int blueRelayPin = 6;    // Blue team relay pin
const int greenRelayPin = 7;    // Green team relay pin

unsigned long gameStartTime = 0;
unsigned long blueStartTime = 0;
unsigned long greenStartTime = 0;

unsigned long blueElapsedTime = 0;
unsigned long greenElapsedTime = 0;

unsigned long blueTime = 0;
unsigned long greenTime = 0;

unsigned long bluePausedTime = 0;
unsigned long greenPausedTime = 0;

const unsigned long gameDuration = 3600000; // in millieconds

bool gameTimerRunning = false;
bool blueTimerRunning = false;
bool greenTimerRunning = false;

bool blueButtonStatePrev = false;
bool greenButtonStatePrev = false;

void setup() {
  lcd.init();
  lcd.backlight();
  
  pinMode(orangeButtonPin, INPUT_PULLUP);
  pinMode(blueButtonPin, INPUT_PULLUP);
  pinMode(greenButtonPin, INPUT_PULLUP);
  pinMode(orangeRelayPin, OUTPUT);
  pinMode(blueRelayPin, OUTPUT);
  pinMode(greenRelayPin, OUTPUT);
  
  lcd.setCursor(2, 0);
  lcd.print("PRESS START"); 
  lcd.setCursor(0, 1);
  lcd.print("B 00:00  G 00:00");
}

void loop() {
  bool orangeButtonState = digitalRead(orangeButtonPin) == LOW;
  bool blueButtonState = digitalRead(blueButtonPin) == LOW;
  bool greenButtonState = digitalRead(greenButtonPin) == LOW;

  unsigned long currentTime = millis();

  // Check if the game timer is running
  if (gameTimerRunning) {
    unsigned long elapsedTime = currentTime - gameStartTime;
    unsigned long remainingTime = (elapsedTime <= gameDuration) ? (gameDuration - elapsedTime) : 0;

    // Calculate remaining game time
    int gameHours = remainingTime / 3600000; // Calculate hours (1 hour = 3600000 milliseconds)
    int gameMinutes = (remainingTime % 3600000) / 60000; // Calculate minutes
    int gameSeconds = (remainingTime / 1000) % 60; // Calculate seconds

    displayTime(gameHours, gameMinutes, gameSeconds);
    
      // Check if the game timer has reached its duration
      if (remainingTime == 0) {
        blueTimerRunning = false; // Stop the blue timer
        greenTimerRunning = false; // Stop the green timer
        gameTimerRunning = false; // Stop the game timer
        displayWinner(); // Display the winner based on total time
      }

    // Blink orange relay if blue or green timers are not running
    if (!blueTimerRunning && !greenTimerRunning) {
      // Blink the orange relay (1 second on, 1 second off)
      unsigned long orangeRelayTime = currentTime % 2000;
      digitalWrite(orangeRelayPin, (orangeRelayTime < 1000));
    } else {
      // Turn off the orange relay when blue or green timers are running
      digitalWrite(orangeRelayPin, LOW);
    }


  } else {
    // Turn off the orange relay when the game timer is not running
    digitalWrite(orangeRelayPin, LOW);
  }

  // Check for game start (orange button press)
  if (orangeButtonState && !gameTimerRunning) {
    startGameTimer(currentTime);
  }

  // Blink blue relay if blue timer is running
  if (blueTimerRunning) {
    // Blink blue relay (1 second on, 1 second off)
    unsigned long blueRelayTime = currentTime % 2000;
    digitalWrite(blueRelayPin, (blueRelayTime < 1000));
  } else {
    // Turn off the blue relay when green timer is running
    digitalWrite(blueRelayPin, LOW);
  }

  // Blink green relay if green timer is running
  if (greenTimerRunning) {
    // Blink green relay (1 second on, 1 second off)
    unsigned long greenRelayTime = currentTime % 2000;
    digitalWrite(greenRelayPin, (greenRelayTime < 1000));
  } else {
    // Turn off the green relay when blue timer is running
    digitalWrite(greenRelayPin, LOW);
  }


// Check blue team button
if (blueButtonState && !blueButtonStatePrev && gameTimerRunning) {
  // If blue timer is not running, start it or resume from where it was paused
  if (!blueTimerRunning) {
    if (blueStartTime == 0) {
      // Start blue timer from 0
      blueStartTime = currentTime;
    } else {
      // Resume blue timer from where it was paused
      blueStartTime = currentTime - blueTime;
    }
    blueTimerRunning = true;
    
  }
  // If green timer was running, pause it and remember the elapsed time
  if (greenTimerRunning) {
    greenPausedTime += currentTime - greenStartTime;
    greenTimerRunning = false;
  }
}

// Check green team button
if (greenButtonState && !greenButtonStatePrev && gameTimerRunning) {
  // If green timer is not running, start it or resume from where it was paused
  if (!greenTimerRunning) {
    if (greenStartTime == 0) {
      // Start green timer from 0
      greenStartTime = currentTime;
    } else {
      // Resume green timer from where it was paused
      greenStartTime = currentTime - greenTime;
    }
    greenTimerRunning = true;
  }
  // If blue timer was running, pause it and remember the elapsed time
  if (blueTimerRunning) {
    bluePausedTime += currentTime - blueStartTime;
    blueTimerRunning = false;
  }
}





  // Store the button states for the next iteration
  blueButtonStatePrev = blueButtonState;
  greenButtonStatePrev = greenButtonState;

  // Update blue timer if running
  if (blueTimerRunning) {
    unsigned long blueElapsed = currentTime - blueStartTime;
    int blueMinutes = blueElapsed / 60000;
    int blueSeconds = (blueElapsed / 1000) % 60;

    lcd.setCursor(0, 1);
    lcd.print("B ");

    if (blueMinutes < 10) {
      lcd.print("0");
    }
    lcd.print(blueMinutes);
    lcd.print(":");

    if (blueSeconds < 10) {
      lcd.print("0");
    }
    lcd.print(blueSeconds);

    blueTime = blueElapsed;
  }

  // Update green timer if running
  if (greenTimerRunning) {
    unsigned long greenElapsed = currentTime - greenStartTime;
    int greenMinutes = greenElapsed / 60000;
    int greenSeconds = (greenElapsed / 1000) % 60;

    lcd.setCursor(9, 1);
    lcd.print("G ");

    if (greenMinutes < 10) {
      lcd.print("0");
    }
    lcd.print(greenMinutes);
    lcd.print(":");

    if (greenSeconds < 10) {
      lcd.print("0");
    }
    lcd.print(greenSeconds);

    greenTime = greenElapsed;
  }

}

void displayTime(int hours, int minutes, int seconds) {
 
  lcd.setCursor(1, 0);
  lcd.print("GAME  ");

  lcd.setCursor(7, 0);
  
  if (hours < 10) {
    lcd.print("0");
  }
  lcd.print(hours);
  lcd.print(":");

  if (minutes < 10) {
    lcd.print("0");
  }
  lcd.print(minutes);
  lcd.print(":");

  if (seconds < 10) {
    lcd.print("0");
  }
  lcd.print(seconds);
}

void startGameTimer(unsigned long currentTime) {
  gameTimerRunning = true;
  gameStartTime = currentTime;
}

void displayWinner() {
  
  int relay = 0;
  
  lcd.setCursor(0, 0);
  lcd.print("               "); // Clear the first line
  
  if (blueTime > greenTime) {
    lcd.setCursor(0, 0);
    lcd.print("BLUE TEAM WINS!");
    digitalWrite(orangeRelayPin, LOW);
    digitalWrite(greenRelayPin, LOW);
  // Blink blue relay  
        while (relay < 500) {  
          digitalWrite(blueRelayPin, LOW);
          delay(125);
          digitalWrite(blueRelayPin, HIGH);
          delay(125);
        relay ++;
        }

  } else if (greenTime > blueTime) {
    lcd.setCursor(0, 0);
    lcd.print("GREEN TEAM WINS!");
    digitalWrite(blueRelayPin, LOW);
    digitalWrite(orangeRelayPin, LOW);
  // Blink green relay 
        while (relay < 500) {
          digitalWrite(greenRelayPin, LOW);
          delay(125);
          digitalWrite(greenRelayPin, HIGH);
          delay(125);  
        relay ++;  
        }

  } else {
    lcd.setCursor(2, 0);
    lcd.print("IT'S A TIE!");
    digitalWrite(blueRelayPin, LOW);
    digitalWrite(greenRelayPin, LOW);    
  // Blink orange relay
        while (relay < 500) {  
          digitalWrite(orangeRelayPin, LOW);
          delay(125);
          digitalWrite(orangeRelayPin, HIGH);
          delay(125);
        relay ++;    
        }
  }
}
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module
NOCOMNCVCCGNDINLED1PWRRelay Module