Code Sketch


Bixuu02
By: Mhalsakant School
Category: Programming
import scala.swing._
import scala.swing.event._
import java.awt.Color
import java.awt.Font
import java.time.LocalTime
import java.time.format.DateTimeFormatter
import scala.collection.mutable

object BixuuSecureChatApp {

  case class ProjectInfo(creatorName: String, projectName: String, category: String, fullDetails: String)
  case class ChatMessage(sender: String, recipient: String, text: String, timestamp: String)

  private val globalProjects = mutable.ListBuffer[ProjectInfo]()
  private val registeredUsersMap = mutable.Map[String, String]() // Name -> Password (Code ????? ??? ???, ????????? ???? ????)
  private val globalMessages = mutable.ListBuffer[ChatMessage]() // Live messages storage

  def main(args: Array[String]): Unit = {
    // Default Bixuu projects
    globalProjects += ProjectInfo("Bixuu", "Weight and Try Project", "Hardware & Sensors", 
      "Project Overview: Weight and Try system is designed to measure and test load limits./n" +
      "Components Required: Load Cell, HX711 Amplifier, Arduino Uno, LCD Display./n" +
      "Step-by-Step Guide:/n1. Connect the load cell to the HX711 module./n2. Wire HX711 to Arduino digital pins./n3. Upload the calibration code to test weight accurately.")
    
    globalProjects += ProjectInfo("Bixuu", "Bixuu Smart AI Assistant", "AI & Automation", 
      "Project Overview: Bixuu integration platform for live messaging and smart responses./n" +
      "Components: Scala Swing, Secure Authentication, Real-time Inbox./n" +
      "Step-by-Step Guide:/n1. Open Bixuu ID using password./n2. Enter your secure password./n3. View live messages with sender ID and timestamp.")

    // Default Bixuu Password (Code ????? ???????? ????? ???, ????????? ???? ????)
    registeredUsersMap("Bixuu") = "24201302@bixuu"

    javax.swing.SwingUtilities.invokeLater(new Runnable {
      def run(): Unit = {
        val loginFrame = new MainLoginPortal()
        loginFrame.visible = true
      }
    })
  }

  class MainLoginPortal extends MainFrame {
    title = "Bixuu - Secure Portal"
    resizable = false
    minimumSize = new Dimension(450, 380)
    centerOnScreen()

    val userField = new TextField(18)
    // JPasswordField ???????????? ????????? ??????? ???????? ???? ????? (??? ????????)
    val passField = new javax.swing.JPasswordField(18)

    val loginBtn = new Button("Login") {
      background = new Color(192, 57, 43); foreground = Color.WHITE; font = new Font("Arial", Font.BOLD, 12)
    }
    val bixuuDirectBtn = new Button("? Open Bixuu ID (Quick Access)") {
      background = new Color(211, 84, 0); foreground = Color.WHITE; font = new Font("Arial", Font.BOLD, 12)
    }
    val createAccBtn = new Button("Create Your Account") {
      background = new Color(41, 128, 185); foreground = Color.WHITE; font = new Font("Arial", Font.BOLD, 12)
    }

    contents = new BoxPanel(Orientation.Vertical) {
      border = Swing.EmptyBorder(20, 25, 20, 25)
      contents += new Label("=== Bixuu Secure Portal ===") { font = new Font("Arial", Font.BOLD, 15); foreground = new Color(192, 57, 43) }
      contents += Swing.VStrut(15)
      contents += new BoxPanel(Orientation.Horizontal) {
        contents += new Label("Your Name / ID: ") { preferredSize = new Dimension(110, 25); font = new Font("Arial", Font.BOLD, 12) }
        contents += userField
      }
      contents += Swing.VStrut(10)
      contents += new BoxPanel(Orientation.Horizontal) {
        contents += new Label("Password:       ") { preferredSize = new Dimension(110, 25); font = new Font("Arial", Font.BOLD, 12) }
        contents += Component.wrap(passField) // ??????? ????? ???????????? ???????? ?????
      }
      contents += Swing.VStrut(15)
      contents += loginBtn
      contents += Swing.VStrut(10)
      contents += bixuuDirectBtn 
      contents += Swing.VStrut(10)
      contents += createAccBtn
      contents += Swing.VStrut(10)
      contents += new Label("<html><center>Note: Enter your secure password to login safely.<br>(Default Bixuu Password is pre-configured in code)</center></html>") {
        font = new Font("Arial", Font.PLAIN, 11); foreground = Color.DARK_GRAY
      }
    }

    listenTo(loginBtn)
    listenTo(bixuuDirectBtn)
    listenTo(createAccBtn)

    reactions += {
      case ButtonClicked(`loginBtn`) =>
        val u = userField.text.trim
        val p = new String(passField.getPassword).trim
        if (u.isEmpty || p.isEmpty) {
          Dialog.showMessage(this, "Please enter your name ID and password!", "Error", Dialog.Message.Error)
        } else if (registeredUsersMap.contains(u) && registeredUsersMap(u) == p) {
          Dialog.showMessage(this, s"Login Successful! Welcome, $u.", "Success", Dialog.Message.Info)
          val dash = new MainDashboardFrame(u)
          dash.visible = true
          this.dispose()
        } else {
          Dialog.showMessage(this, "Invalid Login! Please check your name or type the correct password.", "Error", Dialog.Message.Error)
        }

      case ButtonClicked(`bixuuDirectBtn`) =>
        val enteredPass = javax.swing.JOptionPane.showInputDialog(null, "Please type the password for Bixuu ID:", "Bixuu Secure Access", javax.swing.JOptionPane.PLAIN_MESSAGE)
        if (enteredPass != null) {
          if (enteredPass.trim == "24201302@bixuu") {
            Dialog.showMessage(this, "Bixuu Access Granted! Welcome to Bixuu Dashboard.", "Success", Dialog.Message.Info)
            val dash = new MainDashboardFrame("Bixuu")
            dash.visible = true
            this.dispose()
          } else {
            Dialog.showMessage(this, "Incorrect Password! Access denied for Bixuu.", "Error", Dialog.Message.Error)
          }
        }

      case ButtonClicked(`createAccBtn`) =>
        val reg = new RegistrationWindow()
        reg.visible = true
    }
  }

  class RegistrationWindow extends MainFrame {
    title = "Create Your Account"
    resizable = false
    minimumSize = new Dimension(380, 240)
    centerOnScreen()

    val nameField = new TextField(18)
    val passField = new javax.swing.JPasswordField(18)
    val submitBtn = new Button("Register Account") { background = new Color(39, 174, 96); foreground = Color.WHITE }

    contents = new BoxPanel(Orientation.Vertical) {
      border = Swing.EmptyBorder(20, 20, 20, 20)
      contents += new Label("=== Create Your Account ===") { font = new Font("Arial", Font.BOLD, 14); foreground = new Color(41, 128, 185) }
      contents += Swing.VStrut(15)
      contents += new BoxPanel(Orientation.Horizontal) {
        contents += new Label("Your Name:      ") { preferredSize = new Dimension(100, 25) }
        contents += nameField
      }
      contents += Swing.VStrut(8)
      contents += new BoxPanel(Orientation.Horizontal) {
        contents += new Label("Password:       ") { preferredSize = new Dimension(100, 25) }
        contents += Component.wrap(passField)
      }
      contents += Swing.VStrut(15)
      contents += submitBtn
    }

    listenTo(submitBtn)
    reactions += {
      case ButtonClicked(`submitBtn`) =>
        val name = nameField.text.trim
        val pass = new String(passField.getPassword).trim
        if (name.isEmpty || pass.isEmpty) {
          Dialog.showMessage(this, "Please fill in all details!", "Error", Dialog.Message.Error)
        } else if (registeredUsersMap.contains(name)) {
          Dialog.showMessage(this, "This name is already registered! Choose another name.", "Error", Dialog.Message.Error)
        } else {
          registeredUsersMap(name) = pass
          Dialog.showMessage(this, s"Account '$name' created successfully! You can now login.", "Success", Dialog.Message.Info)
          this.dispose()
        }
    }
  }

  class MainDashboardFrame(currentUserName: String) extends MainFrame {
    title = s"Bixuu Dashboard - Logged in as: $currentUserName"
    minimumSize = new Dimension(1150, 780)
    centerOnScreen()

    val logoutBtn = new Button("<-- Logout") { foreground = new Color(192, 57, 43) }
    val topTitle = new Label(s"Logged in User: $currentUserName | Bixuu Live Chat & Secure Inbox") {
      font = new Font("Arial", Font.BOLD, 12); foreground = new Color(41, 128, 185)
    }

    val searchProjectField = new TextField(20) { text = "Search project name..." }
    val searchBtn = new Button("? Search") { background = new Color(41, 128, 185); foreground = Color.WHITE }
    
    val infoDisplayArea = new TextArea(9, 45) {
      lineWrap = true; wordWrap = true; editable = false
      font = new Font("Monospaced", Font.PLAIN, 12)
      text = "=== Project Information Hub ===/nClick on any project or search to view full details."
    }

    val recipientField = new TextField(15) { text = "Bixuu" }
    val messageField = new TextField(22) { text = "Type your message..." }
    val sendMessageBtn = new Button("? Send Message") { background = new Color(39, 174, 96); foreground = Color.WHITE }
    
    val inboxArea = new TextArea(8, 45) {
      lineWrap = true; wordWrap = true; editable = false
      font = new Font("Arial", Font.PLAIN, 11)
      text = "=== Secure Live Chat Inbox ===/nClick 'See Messages' below to view incoming messages with sender name & time."
    }
    
    // ??????? ??????? ????? (????????? ??????? ????? ???????????)
    val inboxPassField = new javax.swing.JPasswordField(12)
    // ?????? ?????????? ??? "See Messages" ????? ???
    val seeMessagesBtn = new Button("? See Messages (Unlock Inbox)") { background = new Color(52, 152, 219); foreground = Color.WHITE }

    val newTitleField = new TextField(16)
    val newDescArea = new TextArea(3, 30) { lineWrap = true; wordWrap = true }
    val uploadProjectBtn = new Button("? Upload Project") { background = new Color(192, 57, 43); foreground = Color.WHITE }

    val feedBox = new BoxPanel(Orientation.Vertical) { border = Swing.EmptyBorder(5, 5, 5, 5) }
    val feedScroll = new ScrollPane(feedBox) { preferredSize = new Dimension(450, 600) }

    def refreshCommunityFeed(): Unit = {
      feedBox.contents.clear()
      if (globalProjects.isEmpty) {
        feedBox.contents += new Label("No projects found.")
      } else {
        var index = 1
        for (p <- globalProjects) {
          val itemPanel = new BoxPanel(Orientation.Vertical) {
            border = Swing.CompoundBorder(Swing.LineBorder(new Color(192, 57, 43)), Swing.EmptyBorder(8, 8, 8, 8))
            
            contents += new Label(s"[$index] Project:${p.projectName}") {
              font = new Font("Arial", Font.BOLD, 12); foreground = new Color(192, 57, 43)
            }
            
            contents += new Label(s"Creator: ${p.creatorName} /vert{} Category:${p.category}") { 
              font = new Font("Arial", Font.ITALIC, 11) 
            }
            contents += Swing.VStrut(5)

            val seeInfoBtn = new Button("View Full Project Information") {
              font = new Font("Arial", Font.BOLD, 11)
              background = new Color(52, 152, 219)
              foreground = Color.WHITE
            }

            contents += seeInfoBtn

            listenTo(seeInfoBtn)
            reactions += {
              case ButtonClicked(`seeInfoBtn`) =>
                infoDisplayArea.text = s"=== FULL PROJECT DETAILS ===/n/n" +
                  s"Project Name: ${p.projectName}/n" +
                  s"Created By: ${p.creatorName}/n" +
                  s"Category: ${p.category}/n/n" +
                  s"${p.fullDetails}"
                recipientField.text = p.creatorName
            }
          }
          feedBox.contents += itemPanel
          feedBox.contents += Swing.VStrut(8)
          index += 1
        }
      }
      feedBox.revalidate()
      feedBox.repaint()
    }

    def loadAndDisplayInbox(): Unit = {
      val enteredPass = new String(inboxPassField.getPassword).trim
      val isValid = registeredUsersMap.contains(currentUserName) && registeredUsersMap(currentUserName) == enteredPass

      if (isValid) {
        val myMessages = globalMessages.filter(_.recipient.equalsIgnoreCase(currentUserName))
        if (myMessages.isEmpty) {
          inboxArea.text = s"=== Secure Live Chat Inbox ($currentUserName) ===/nNo messages received yet."
        } else {
          val sb = new StringBuilder(s"=== Secure Live Chat Inbox ($currentUserName) ===/n/n")
          for (m <- myMessages) {
            // ??? ??????? ??? (Sender ID), ????? ??? ???? ??????? (Timestamp) ???? ????????? ?????
            sb.append(s"? Time: [%s]/n? Sender ID: %s/n? Message: %s/n-----------------------------------/n".format(m.timestamp, m.sender, m.text))
          }
          inboxArea.text = sb.toString()
        }
        Dialog.showMessage(this, "Password Verified! Inbox unlocked successfully.", "Success", Dialog.Message.Info)
      } else {
        Dialog.showMessage(this, "Incorrect Password! Please type your correct password to see messages.", "Error", Dialog.Message.Error)
      }
    }

    refreshCommunityFeed()

    val topPanel = new BoxPanel(Orientation.Horizontal) {
      border = Swing.EmptyBorder(10, 15, 10, 15)
      contents += logoutBtn; contents += Swing.HStrut(15); contents += topTitle
    }

    val centerPanel = new BoxPanel(Orientation.Horizontal) {
      border = Swing.EmptyBorder(15, 15, 15, 15)

      val leftCol = new BoxPanel(Orientation.Vertical) {
        contents += new Label("<html><b>1. Search & Explore Project Info:</b></html>")
        contents += Swing.VStrut(5)
        contents += new BoxPanel(Orientation.Horizontal) {
          contents += searchProjectField; contents += Swing.HStrut(10); contents += searchBtn
        }
        contents += Swing.VStrut(5)
        contents += new ScrollPane(infoDisplayArea)
        contents += Swing.VStrut(10)

        contents += new Label("<html><b>2. Bixuu Live Chat & Messaging:</b></html>")
        contents += Swing.VStrut(3)
        contents += new BoxPanel(Orientation.Horizontal) {
          contents += new Label("To User ID: ") { preferredSize = new Dimension(75, 20) }
          contents += recipientField
        }
        contents += Swing.VStrut(3)
        contents += new BoxPanel(Orientation.Horizontal) {
          contents += new Label("Message:    ") { preferredSize = new Dimension(75, 20) }
          contents += messageField; contents += Swing.HStrut(5); contents += sendMessageBtn
        }
        contents += Swing.VStrut(5)
        
        contents += new BoxPanel(Orientation.Horizontal) {
          contents += new Label("Password: ") { preferredSize = new Dimension(70, 20) }
          contents += Component.wrap(inboxPassField)
          contents += Swing.HStrut(5)
          contents += seeMessagesBtn // "See Messages" ????? ??? ??? ????? ???
        }
        contents += Swing.VStrut(3)
        contents += new ScrollPane(inboxArea)
        contents += Swing.VStrut(10)

        contents += new Label("<html><b>3. Upload Your Own Project:</b></html>")
        contents += new BoxPanel(Orientation.Horizontal) {
          contents += new Label("Title: ") { preferredSize = new Dimension(45, 20) }
          contents += newTitleField
        }
        contents += Swing.VStrut(3)
        contents += new Label("Details (How to build):")
        contents += new ScrollPane(newDescArea)
        contents += Swing.VStrut(3)
        contents += uploadProjectBtn
      }

      val rightCol = new BoxPanel(Orientation.Vertical) {
        border = Swing.EmptyBorder(0, 15, 0, 0)
        contents += new Label("<html><b>All Community Projects:</b></html>") {
          font = new Font("Arial", Font.BOLD, 12); foreground = new Color(192, 57, 43)
        }
        contents += Swing.VStrut(5)
        contents += feedScroll
      }

      contents += leftCol
      contents += Swing.HStrut(15)
      contents += rightCol
    }

    contents = new BorderPanel {
      layout(topPanel) = BorderPanel.Position.North
      layout(centerPanel) = BorderPanel.Position.Center
    }

    listenTo(logoutBtn)
    listenTo(searchBtn)
    listenTo(sendMessageBtn)
    listenTo(seeMessagesBtn)
    listenTo(uploadProjectBtn)

    reactions += {
      case ButtonClicked(`logoutBtn`) =>
        val login = new MainLoginPortal()
        login.visible = true
        this.dispose()

      case ButtonClicked(`searchBtn`) =>
        val query = searchProjectField.text.trim.toLowerCase
        val found = globalProjects.find(p => p.projectName.toLowerCase.contains(query) || p.creatorName.toLowerCase.contains(query))
        if (found.isDefined) {
          val p = found.get
          infoDisplayArea.text = s"=== SEARCH RESULT ===/n/n" +
            s"Project Name: ${p.projectName}/n" +
            s"Creator: ${p.creatorName}/n" +
            s"Category: ${p.category}/n/n" +
            s"${p.fullDetails}"
          recipientField.text = p.creatorName
        } else {
          infoDisplayArea.text = "Project not found! Please check the search keyword."
        }

      case ButtonClicked(`sendMessageBtn`) =>
        val receiver = recipientField.text.trim
        val msg = messageField.text.trim
        val currentTimeStr = LocalTime.now().format(DateTimeFormatter.ofPattern("hh:mm:ss a"))

        if (receiver.isEmpty || msg.isEmpty) {
          Dialog.showMessage(this, "Please enter recipient user ID and message!", "Error", Dialog.Message.Error)
        } else if (!receiver.equalsIgnoreCase("Bixuu") && !registeredUsersMap.contains(receiver)) {
          Dialog.showMessage(this, s"User ID '$receiver' is not registered! They must register first.", "Error", Dialog.Message.Error)
        } else if (receiver.equalsIgnoreCase(currentUserName)) {
          Dialog.showMessage(this, "You cannot send a message to yourself!", "Error", Dialog.Message.Error)
        } else {
          // 1. ?????? ????? ????? ??? ????????? ??????? ????
          globalMessages += ChatMessage(currentUserName, receiver, msg, currentTimeStr)
          
          // 2. ?? ????? Bixuu ??? ?????? ????, ?? ??? ??????? ??????
          if (receiver.equalsIgnoreCase("Bixuu")) {
            val botReplyText = s"Hello $currentUserName! Bixuu bot received your query: '$msg'. Automated response: All parameters verified successfully."
            globalMessages += ChatMessage("Bixuu", currentUserName, botReplyText, currentTimeStr)
            Dialog.showMessage(this, s"Your message sent successfully! Click 'See Messages' to view Bixuu's reply.", "Success", Dialog.Message.Info)
          } else {
            Dialog.showMessage(this, s"Your message has been successfully sent to $receiver!", "Success", Dialog.Message.Info)
          }

          messageField.text = ""
        }

      case ButtonClicked(`seeMessagesBtn`) =>
        loadAndDisplayInbox()

      case ButtonClicked(`uploadProjectBtn`) =>
        val title = newTitleField.text.trim
        val details = newDescArea.text.trim
        if (title.isEmpty || details.isEmpty) {
          Dialog.showMessage(this, "Please enter project title and details!", "Error", Dialog.Message.Error)
        } else {
          val newProj = ProjectInfo(currentUserName, title, "Community Custom Project", details)
          globalProjects += newProj
          newTitleField.text = ""
          newDescArea.text = ""
          refreshCommunityFeed()
          Dialog.showMessage(this, "Your project has been successfully uploaded to the community!", "Success", Dialog.Message.Info)
        }
    }
  }
}

BixuuSecureChatApp.main(Array())