Code Sketch
Bixuu02_project_help
Category: Programming
import javax.swing._
import java.awt._
import java.awt.event._
import java.util.ArrayList
// ============================================================
// BIX-02 PROJECT LAB
// FULL PROJECT RECOMMENDATION SYSTEM
// KOJO + SCALA + JAVA SWING/AWT
// ============================================================
val APP_NAME = "BIX-02 PROJECT LAB"
val PASSWORD = "Bix-02"
// ============================================================
// MAIN WINDOW
// ============================================================
val frame = new JFrame(APP_NAME)
frame.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE
)
frame.setSize(1200, 780)
frame.setLocationRelativeTo(null)
// ============================================================
// COLORS
// ============================================================
val BG = new Color(10, 16, 28)
val PANEL = new Color(20, 29, 45)
val PANEL2 = new Color(31, 45, 68)
val TEXT = new Color(240, 246, 255)
val MUTED = new Color(170, 185, 210)
val BLUE = new Color(70, 190, 255)
val GREEN = new Color(75, 220, 145)
val ORANGE = new Color(255, 180, 70)
val RED = new Color(255, 100, 100)
// ============================================================
// COMPONENT DATA
// ============================================================
case class ComponentInfo(
name: String,
category: String,
description: String
)
val components = Array(
ComponentInfo(
"Arduino UNO",
"Controller",
"A microcontroller board used to control sensors, LEDs, displays and motors."
),
ComponentInfo(
"Ultrasonic Sensor",
"Sensor",
"Measures approximate distance using ultrasonic waves."
),
ComponentInfo(
"LDR",
"Sensor",
"Detects surrounding light intensity."
),
ComponentInfo(
"IR Sensor",
"Sensor",
"Detects objects or infrared signals."
),
ComponentInfo(
"PIR Sensor",
"Sensor",
"Detects motion in a surrounding area."
),
ComponentInfo(
"DHT11",
"Sensor",
"Measures temperature and humidity."
),
ComponentInfo(
"Soil Moisture Sensor",
"Sensor",
"Detects relative soil moisture."
),
ComponentInfo(
"Gas Sensor",
"Sensor",
"Provides readings related to certain gases."
),
ComponentInfo(
"LED",
"Output",
"Basic light indicator."
),
ComponentInfo(
"RGB LED",
"Output",
"Multi-colour LED used for lighting demonstrations."
),
ComponentInfo(
"Buzzer",
"Output",
"Produces sound for alerts and demonstrations."
),
ComponentInfo(
"Servo Motor",
"Motor",
"Motor that can move to controlled angles."
),
ComponentInfo(
"DC Motor",
"Motor",
"Motor used for continuous rotation."
),
ComponentInfo(
"Motor Driver",
"Controller",
"Module used to control suitable DC motors."
),
ComponentInfo(
"LCD Display",
"Display",
"Displays text and numerical information."
),
ComponentInfo(
"OLED Display",
"Display",
"Compact display for text and simple graphics."
),
ComponentInfo(
"Push Button",
"Input",
"Simple digital input switch."
),
ComponentInfo(
"Potentiometer",
"Input",
"Variable resistor useful for analog input demonstrations."
),
ComponentInfo(
"Relay Module",
"Output",
"Electronic switching module."
),
ComponentInfo(
"Bluetooth Module",
"Communication",
"Wireless communication module for compatible projects."
),
ComponentInfo(
"Breadboard",
"Basic",
"Used for temporary circuit construction."
),
ComponentInfo(
"Jumper Wires",
"Basic",
"Used for connecting components."
),
ComponentInfo(
"Resistor",
"Basic",
"Used to limit current in suitable circuits."
),
ComponentInfo(
"Battery Pack",
"Power",
"Portable power source for compatible circuits."
)
)
// ============================================================
// SELECTED MATERIALS
// ============================================================
var selected =
Array.fill[Boolean](
components.length
)(false)
// ============================================================
// PROJECT DATA
// ============================================================
case class ProjectInfo(
name: String,
category: String,
creator: String,
reference: String,
description: String,
required: Array[String],
wiring: Array[String],
steps: Array[String],
working: String,
uses: String,
difficulty: String
)
// ============================================================
// PROJECT DATABASE
// ============================================================
val projects = Array(
ProjectInfo(
"Smart Distance Alarm",
"Sensor System",
"BIX-02 Project Database",
"Educational reference project",
"Detects a nearby object and provides a visual and sound indication.",
Array(
"Arduino UNO",
"Ultrasonic Sensor",
"Buzzer",
"LED",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"Ultrasonic sensor power -> suitable supply",
"TRIG -> suitable Arduino digital pin",
"ECHO -> suitable Arduino digital pin",
"Buzzer -> Arduino output",
"LED -> Arduino output through resistor",
"Connect the circuit ground correctly"
),
Array(
"Connect the ultrasonic sensor.",
"Connect the LED through a resistor.",
"Connect the buzzer.",
"Program Arduino to read distance.",
"Set a suitable demonstration threshold.",
"Test with objects at different distances."
),
"The ultrasonic sensor provides timing information related to its returning echo. Arduino processes the reading and can activate the indicators when the programmed condition is reached.",
"Distance sensing and robotics demonstrations.",
"Easy"
),
ProjectInfo(
"Parking Distance Indicator",
"Smart Transport",
"BIX-02 Project Database",
"Educational reference project",
"Shows different distance states using an ultrasonic sensor and indicators.",
Array(
"Arduino UNO",
"Ultrasonic Sensor",
"LED",
"Buzzer",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"Ultrasonic TRIG -> digital output",
"Ultrasonic ECHO -> digital input",
"LED -> digital outputs through resistors",
"Buzzer -> digital output"
),
Array(
"Install the ultrasonic sensor on the model.",
"Connect the indicator LEDs.",
"Connect the buzzer.",
"Read the distance.",
"Create different distance ranges.",
"Show the ranges using the indicators."
),
"Arduino converts the distance reading into programmed states. Different states can be represented using LEDs and sound.",
"Smart transport and sensor demonstrations.",
"Medium"
),
ProjectInfo(
"Automatic Night Lamp",
"Smart Home",
"BIX-02 Project Database",
"Educational reference project",
"Automatically controls a light according to surrounding brightness.",
Array(
"Arduino UNO",
"LDR",
"LED",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"LDR -> Arduino analog input",
"LED -> Arduino output through resistor",
"Connect common ground",
"Use suitable power"
),
Array(
"Connect the LDR.",
"Connect the LED.",
"Read the light level.",
"Choose a suitable threshold.",
"Turn the LED on when the environment becomes darker.",
"Test in different lighting conditions."
),
"The LDR provides an analog reading related to light intensity. Arduino uses that reading to control the LED.",
"Automatic lighting and electronics learning.",
"Easy"
),
ProjectInfo(
"Smart Light Controller",
"Smart Home",
"BIX-02 Project Database",
"Educational reference project",
"Combines a light sensor and user controls for a programmable light system.",
Array(
"Arduino UNO",
"LDR",
"LED",
"Push Button",
"Potentiometer",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"LDR -> analog input",
"Push Button -> digital input",
"Potentiometer -> analog input",
"LED -> digital output through resistor"
),
Array(
"Connect the LDR.",
"Connect the push button.",
"Connect the potentiometer.",
"Connect the LED.",
"Program the control modes.",
"Test each mode."
),
"Arduino combines sensor readings with user input and controls the LED according to the programmed rules.",
"Smart-home and electronics demonstrations.",
"Medium"
),
ProjectInfo(
"Temperature Monitor",
"Environment",
"BIX-02 Project Database",
"Educational reference project",
"Measures temperature and humidity and displays the information.",
Array(
"Arduino UNO",
"DHT11",
"LCD Display",
"Breadboard",
"Jumper Wires"
),
Array(
"DHT11 data -> Arduino digital input",
"DHT11 power -> suitable supply",
"LCD -> appropriate interface",
"Connect grounds correctly"
),
Array(
"Connect the DHT11 sensor.",
"Connect the display.",
"Read temperature and humidity.",
"Format the readings.",
"Display the values."
),
"The DHT11 provides environmental readings that Arduino can process and display.",
"Environmental science and electronics learning.",
"Easy"
),
ProjectInfo(
"Smart Plant Monitor",
"Agriculture",
"BIX-02 Project Database",
"Educational reference project",
"Monitors soil moisture and provides a simple plant-condition indication.",
Array(
"Arduino UNO",
"Soil Moisture Sensor",
"LCD Display",
"LED",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"Soil sensor signal -> Arduino analog input",
"LCD -> appropriate interface",
"LED -> output through resistor"
),
Array(
"Place the soil sensor in the soil.",
"Connect its signal.",
"Read the moisture value.",
"Define demonstration ranges.",
"Display the soil condition."
),
"The sensor provides an electrical reading related to soil moisture. Arduino interprets that reading and displays the programmed condition.",
"Plant science, agriculture and sensor learning.",
"Easy"
),
ProjectInfo(
"Automatic Door Model",
"Automation",
"BIX-02 Project Database",
"Educational reference project",
"A model door that moves using a servo when an object is detected.",
Array(
"Arduino UNO",
"Ultrasonic Sensor",
"Servo Motor",
"Breadboard",
"Jumper Wires"
),
Array(
"Ultrasonic sensor -> Arduino digital pins",
"Servo signal -> suitable Arduino output",
"Servo -> suitable power",
"Connect grounds correctly"
),
Array(
"Build a small model door.",
"Attach the servo mechanism.",
"Connect the ultrasonic sensor.",
"Read the distance.",
"Move the servo according to the programmed condition."
),
"The sensor detects a nearby object and Arduino commands the servo to move to a selected angle.",
"Robotics and automation demonstrations.",
"Medium"
),
ProjectInfo(
"Motion Security Indicator",
"Motion Detection",
"BIX-02 Project Database",
"Educational reference project",
"Uses a motion sensor to control visual and sound indicators.",
Array(
"Arduino UNO",
"PIR Sensor",
"LED",
"Buzzer",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"PIR output -> Arduino digital input",
"LED -> digital output through resistor",
"Buzzer -> digital output",
"Connect common ground"
),
Array(
"Connect the PIR sensor.",
"Connect the LED.",
"Connect the buzzer.",
"Read the PIR signal.",
"Activate the indicators according to the program."
),
"The PIR sensor provides a digital signal related to detected motion. Arduino uses that signal to control the indicators.",
"Motion sensing and automation learning.",
"Easy"
),
ProjectInfo(
"RGB Colour Controller",
"Lighting",
"BIX-02 Project Database",
"Educational reference project",
"Creates programmable colour patterns using an RGB LED.",
Array(
"Arduino UNO",
"RGB LED",
"Potentiometer",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"RGB channels -> Arduino outputs through suitable resistors",
"Potentiometer -> analog input",
"Connect the required common connection"
),
Array(
"Connect the RGB LED.",
"Connect the potentiometer.",
"Read the potentiometer.",
"Map input values to colour combinations.",
"Test several patterns."
),
"Arduino controls the RGB channels and can use the potentiometer as a user input.",
"Colour mixing and electronics learning.",
"Medium"
),
ProjectInfo(
"Digital Visitor Counter",
"Automation",
"BIX-02 Project Database",
"Educational reference project",
"Counts detected events and displays the count.",
Array(
"Arduino UNO",
"IR Sensor",
"LCD Display",
"Breadboard",
"Jumper Wires"
),
Array(
"IR output -> Arduino digital input",
"LCD -> appropriate interface",
"Connect common ground"
),
Array(
"Position the IR sensor.",
"Detect an object crossing the sensor.",
"Increase the counter.",
"Display the count.",
"Test repeated detections."
),
"Arduino detects the sensor event and updates a counter stored by the program.",
"Learning about digital inputs and counters.",
"Easy"
),
ProjectInfo(
"Bluetooth Robot Controller",
"Robotics",
"BIX-02 Project Database",
"Educational reference project",
"Demonstrates wireless control of a compatible small robot platform.",
Array(
"Arduino UNO",
"Bluetooth Module",
"Motor Driver",
"DC Motor",
"Battery Pack",
"Jumper Wires"
),
Array(
"Bluetooth module -> suitable communication interface",
"Motor driver -> Arduino control pins",
"Motors -> motor-driver outputs",
"Use suitable motor power",
"Connect signal and ground connections correctly"
),
Array(
"Build the motor section.",
"Connect the motor driver.",
"Connect the communication module.",
"Define simple movement commands.",
"Test commands one at a time."
),
"Commands received by the communication module can be interpreted by Arduino and converted into motor-control signals.",
"Robotics and communication learning.",
"Advanced"
),
ProjectInfo(
"Gas Sensor Monitor",
"Environment",
"BIX-02 Project Database",
"Educational reference project",
"Demonstrates gas-sensor readings with a display and indicators.",
Array(
"Arduino UNO",
"Gas Sensor",
"LCD Display",
"LED",
"Buzzer",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"Gas sensor signal -> Arduino input",
"LCD -> appropriate interface",
"LED -> output through resistor",
"Buzzer -> digital output"
),
Array(
"Connect the sensor according to its module documentation.",
"Read the sensor value.",
"Display the reading.",
"Create an educational demonstration threshold.",
"Use indicators for the programmed state."
),
"Arduino reads the sensor signal and can display or indicate the resulting value.",
"Environmental sensor education.",
"Medium"
),
ProjectInfo(
"Temperature Alert System",
"Environment",
"BIX-02 Project Database",
"Educational reference project",
"Uses a temperature sensor with a display and alert output.",
Array(
"Arduino UNO",
"DHT11",
"Buzzer",
"LED",
"LCD Display",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"DHT11 data -> Arduino digital input",
"LCD -> appropriate interface",
"LED -> output through resistor",
"Buzzer -> output"
),
Array(
"Connect the DHT11.",
"Connect the display.",
"Connect the LED and buzzer.",
"Read the temperature.",
"Create a suitable demonstration threshold.",
"Show the result."
),
"Arduino reads the temperature and compares it with a programmed threshold. The display and indicators can show the resulting state.",
"Environmental monitoring education.",
"Medium"
),
ProjectInfo(
"Smart Motion Light",
"Smart Home",
"BIX-02 Project Database",
"Educational reference project",
"Combines motion detection and light detection for an educational smart-light demonstration.",
Array(
"Arduino UNO",
"PIR Sensor",
"LDR",
"LED",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"PIR -> digital input",
"LDR -> analog input",
"LED -> digital output through resistor",
"Connect common ground"
),
Array(
"Connect the PIR sensor.",
"Connect the LDR.",
"Connect the LED.",
"Read both sensor values.",
"Program the lighting condition.",
"Test different conditions."
),
"Arduino combines motion and light-level readings to determine the programmed LED behaviour.",
"Smart-home and sensor integration learning.",
"Medium"
),
ProjectInfo(
"Button Controlled LED",
"Basic Electronics",
"BIX-02 Project Database",
"Educational reference project",
"A beginner-friendly digital input and output project.",
Array(
"Arduino UNO",
"Push Button",
"LED",
"Resistor",
"Breadboard",
"Jumper Wires"
),
Array(
"Push button -> digital input",
"LED -> digital output through resistor",
"Connect common ground"
),
Array(
"Connect the button.",
"Connect the LED.",
"Read the button state.",
"Control the LED.",
"Test repeated button presses."
),
"Arduino reads the button input and changes the LED state according to the program.",
"Learning about digital inputs and outputs.",
"Easy"
)
)
// ============================================================
// COMMON UI HELPERS
// ============================================================
def makePanel(): JPanel = {
val p = new JPanel()
p.setBackground(BG)
p
}
def makeTitle(
textValue: String,
size: Int
): JLabel = {
val l =
new JLabel(textValue)
l.setFont(
new Font(
"Arial",
Font.BOLD,
size
)
)
l.setForeground(TEXT)
l
}
def makeNormal(
textValue: String
): JLabel = {
val l =
new JLabel(textValue)
l.setFont(
new Font(
"Arial",
Font.PLAIN,
14
)
)
l.setForeground(MUTED)
l
}
def makeButton(
textValue: String
): JButton = {
val b =
new JButton(textValue)
b.setFont(
new Font(
"Arial",
Font.BOLD,
14
)
)
b.setForeground(TEXT)
b.setBackground(PANEL2)
b.setFocusPainted(false)
b.setBorder(
BorderFactory.createEmptyBorder(
11,
18,
11,
18
)
)
b
}
// ============================================================
// SELECTED MATERIAL HELPERS
// ============================================================
def selectedCount(): Int = {
var count = 0
var i = 0
while (
i < selected.length
) {
if (selected(i)) {
count += 1
}
i += 1
}
count
}
def hasComponent(
componentName: String
): Boolean = {
var i = 0
while (
i < components.length
) {
if (
selected(i) &&
components(i).name == componentName
) {
return true
}
i += 1
}
false
}
def selectedNames(): Array[String] = {
val list =
new ArrayList[String]()
var i = 0
while (
i < components.length
) {
if (selected(i)) {
list.add(
components(i).name
)
}
i += 1
}
list.toArray(
new Array[String](
list.size()
)
)
}
// ============================================================
// ROBOT PANEL
// ============================================================
class RobotPanel
extends JPanel {
setBackground(BG)
setPreferredSize(
new Dimension(
280,
360
)
)
override def paintComponent(
g: Graphics
): Unit = {
super.paintComponent(g)
val g2 =
g.asInstanceOf[Graphics2D]
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
val cx =
getWidth / 2
// Glow
g2.setColor(
new Color(
25,
80,
125
)
)
g2.fillOval(
cx - 120,
30,
240,
240
)
// Antenna
g2.setColor(BLUE)
g2.setStroke(
new BasicStroke(5)
)
g2.drawLine(
cx,
65,
cx,
32
)
g2.fillOval(
cx - 9,
17,
18,
18
)
// Head
g2.setColor(
new Color(
210,
222,
235
)
)
g2.fillRoundRect(
cx - 95,
70,
190,
145,
32,
32
)
g2.setColor(
new Color(
90,
110,
135
)
)
g2.drawRoundRect(
cx - 95,
70,
190,
145,
32,
32
)
// Eyes
g2.setColor(BLUE)
g2.fillOval(
cx - 62,
112,
36,
45
)
g2.fillOval(
cx + 26,
112,
36,
45
)
// Eye highlights
g2.setColor(Color.WHITE)
g2.fillOval(
cx - 53,
120,
9,
9
)
g2.fillOval(
cx + 35,
120,
9,
9
)
// Mouth
g2.setColor(
new Color(
45,
60,
75
)
)
g2.fillRoundRect(
cx - 48,
174,
96,
17,
10,
10
)
// Body
g2.setColor(
new Color(
190,
207,
220
)
)
g2.fillRoundRect(
cx - 88,
235,
176,
95,
25,
25
)
g2.setColor(
new Color(
90,
110,
135
)
)
g2.drawRoundRect(
cx - 88,
235,
176,
95,
25,
25
)
// Chest screen
g2.setColor(
new Color(
20,
30,
45
)
)
g2.fillRoundRect(
cx - 50,
255,
100,
48,
10,
10
)
g2.setColor(GREEN)
g2.fillOval(
cx - 28,
272,
11,
11
)
g2.fillOval(
cx - 5,
272,
11,
11
)
g2.fillOval(
cx + 18,
272,
11,
11
)
// Arms
g2.setColor(
new Color(
165,
188,
207
)
)
g2.fillRoundRect(
cx - 120,
238,
28,
80,
15,
15
)
g2.fillRoundRect(
cx + 92,
238,
28,
80,
15,
15
)
// Name
g2.setColor(TEXT)
g2.setFont(
new Font(
"Arial",
Font.BOLD,
21
)
)
val robotName =
"BIX-02"
val fm =
g2.getFontMetrics
g2.drawString(
robotName,
cx -
fm.stringWidth(robotName) / 2,
355
)
}
}
// ============================================================
// TOP BAR
// ============================================================
def topBar(
titleValue: String
): JPanel = {
val p =
new JPanel(
new BorderLayout()
)
p.setBackground(PANEL)
p.setBorder(
BorderFactory.createEmptyBorder(
12,
18,
12,
18
)
)
val left =
new JPanel(
new FlowLayout(
FlowLayout.LEFT,
12,
0
)
)
left.setOpaque(false)
val logo =
makeTitle(
"BIX-02",
24
)
logo.setForeground(BLUE)
left.add(logo)
left.add(
makeTitle(
titleValue,
19
)
)
p.add(
left,
BorderLayout.WEST
)
val status =
makeNormal(
"PROJECT ENGINE READY"
)
status.setForeground(GREEN)
p.add(
status,
BorderLayout.EAST
)
p
}
// ============================================================
// SCREEN SWITCH
// ============================================================
def switchPanel(
panel: JPanel
): Unit = {
frame.setContentPane(panel)
frame.revalidate()
frame.repaint()
}
// ============================================================
// LOGIN SCREEN
// ============================================================
def loginPanel(): JPanel = {
val root =
makePanel()
root.setLayout(
new BorderLayout()
)
root.add(
topBar(
"SECURE PROJECT LAB"
),
BorderLayout.NORTH
)
val center =
new JPanel(
new GridBagLayout()
)
center.setBackground(BG)
val box =
new JPanel()
box.setBackground(PANEL)
box.setLayout(
new BoxLayout(
box,
BoxLayout.Y_AXIS
)
)
box.setBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(
new Color(
55,
80,
110
)
),
BorderFactory.createEmptyBorder(
25,
35,
25,
35
)
)
)
val robot =
new RobotPanel()
box.add(robot)
val label =
makeTitle(
"ENTER BIX-02 PASSWORD",
17
)
label.setAlignmentX(
Component.CENTER_ALIGNMENT
)
box.add(label)
box.add(
Box.createVerticalStrut(10)
)
val passwordField =
new JPasswordField()
passwordField.setFont(
new Font(
"Arial",
Font.PLAIN,
20
)
)
passwordField.setHorizontalAlignment(
SwingConstants.CENTER
)
passwordField.setMaximumSize(
new Dimension(
280,
42
)
)
box.add(passwordField)
box.add(
Box.createVerticalStrut(12)
)
val enter =
makeButton(
"ENTER BIX-02 PROJECT LAB"
)
enter.setAlignmentX(
Component.CENTER_ALIGNMENT
)
val status =
makeNormal(
"Password required"
)
status.setAlignmentX(
Component.CENTER_ALIGNMENT
)
enter.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
val value =
new String(
passwordField.getPassword
)
if (
value == PASSWORD
) {
switchPanel(
homePanel()
)
} else {
status.setText(
"Incorrect password"
)
status.setForeground(
RED
)
passwordField.setText("")
}
}
}
)
passwordField.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
enter.doClick()
}
}
)
box.add(enter)
box.add(
Box.createVerticalStrut(10)
)
box.add(status)
center.add(box)
root.add(
center,
BorderLayout.CENTER
)
root
}
// ============================================================
// HOME SCREEN
// ============================================================
def homePanel(): JPanel = {
val root =
makePanel()
root.setLayout(
new BorderLayout()
)
root.add(
topBar("HOME"),
BorderLayout.NORTH
)
val center =
new JPanel(
new GridBagLayout()
)
center.setBackground(BG)
val content =
new JPanel(
new BorderLayout(
30,
10
)
)
content.setBackground(BG)
val robot =
new RobotPanel()
content.add(
robot,
BorderLayout.WEST
)
val right =
new JPanel()
right.setBackground(BG)
right.setLayout(
new BoxLayout(
right,
BoxLayout.Y_AXIS
)
)
val heading =
makeTitle(
"WELCOME TO BIX-02",
31
)
val description =
new JTextArea(
"PROJECT LAB\n\n" +
"Choose the electronic materials you have.\n\n" +
"BIX-02 compares your selected materials\n" +
"with its project database.\n\n" +
"You can then browse PROJECT 1,\n" +
"PROJECT 2, PROJECT 3 and more."
)
description.setEditable(false)
description.setLineWrap(true)
description.setWrapStyleWord(true)
description.setFont(
new Font(
"Arial",
Font.PLAIN,
16
)
)
description.setForeground(MUTED)
description.setBackground(BG)
val create =
makeButton(
"CREATE PROJECT"
)
create.setMaximumSize(
new Dimension(
390,
55
)
)
val materials =
makeButton(
"VIEW ALL MATERIALS"
)
materials.setMaximumSize(
new Dimension(
390,
55
)
)
create.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
switchPanel(
createProjectPanel()
)
}
}
)
materials.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
switchPanel(
materialsPanel()
)
}
}
)
right.add(heading)
right.add(
Box.createVerticalStrut(20)
)
right.add(description)
right.add(
Box.createVerticalStrut(25)
)
right.add(create)
right.add(
Box.createVerticalStrut(15)
)
right.add(materials)
content.add(
right,
BorderLayout.CENTER
)
center.add(content)
root.add(
center,
BorderLayout.CENTER
)
root
}
// ============================================================
// ALL MATERIALS SCREEN
// ============================================================
def materialsPanel(): JPanel = {
val root =
makePanel()
root.setLayout(
new BorderLayout(
10,
10
)
)
root.add(
topBar(
"ALL PROJECT MATERIALS"
),
BorderLayout.NORTH
)
val model =
new DefaultListModel[String]()
var i = 0
while (
i < components.length
) {
model.addElement(
components(i).name +
" | " +
components(i).category
)
i += 1
}
val list =
new JList[String](model)
list.setFont(
new Font(
"Arial",
Font.PLAIN,
15
)
)
list.setForeground(TEXT)
list.setBackground(PANEL)
val information =
new JTextArea()
information.setEditable(false)
information.setLineWrap(true)
information.setWrapStyleWord(true)
information.setFont(
new Font(
"Arial",
Font.PLAIN,
15
)
)
information.setForeground(TEXT)
information.setBackground(PANEL)
list.addListSelectionListener(
new javax.swing.event.ListSelectionListener {
def valueChanged(
e: javax.swing.event.ListSelectionEvent
): Unit = {
if (
!e.getValueIsAdjusting &&
list.getSelectedIndex >= 0
) {
val c =
components(
list.getSelectedIndex
)
information.setText(
"MATERIAL\n\n" +
c.name +
"\n\nCATEGORY\n" +
c.category +
"\n\nDESCRIPTION\n\n" +
c.description
)
}
}
}
)
val split =
new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT,
new JScrollPane(list),
new JScrollPane(information)
)
split.setDividerLocation(480)
root.add(
split,
BorderLayout.CENTER
)
val bottom =
new JPanel(
new FlowLayout(
FlowLayout.RIGHT
)
)
bottom.setBackground(BG)
val back =
makeButton("BACK")
back.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
switchPanel(
homePanel()
)
}
}
)
bottom.add(back)
root.add(
bottom,
BorderLayout.SOUTH
)
root
}
// ============================================================
// CREATE PROJECT SCREEN
// ============================================================
def createProjectPanel(): JPanel = {
val root =
makePanel()
root.setLayout(
new BorderLayout(
10,
10
)
)
root.add(
topBar(
"CREATE YOUR PROJECT"
),
BorderLayout.NORTH
)
// ----------------------------------------------------------
// LEFT MATERIAL PANEL
// ----------------------------------------------------------
val left =
new JPanel(
new BorderLayout(
8,
8
)
)
left.setBackground(BG)
left.add(
makeTitle(
"CHOOSE MATERIALS",
20
),
BorderLayout.NORTH
)
val materialBox =
new JPanel()
materialBox.setLayout(
new BoxLayout(
materialBox,
BoxLayout.Y_AXIS
)
)
materialBox.setBackground(PANEL)
val materialScroll =
new JScrollPane(
materialBox
)
materialScroll.setBorder(
BorderFactory.createLineBorder(
new Color(
50,
70,
95
)
)
)
val selectedLabel =
makeNormal(
"Selected materials: " +
selectedCount()
)
selectedLabel.setForeground(
GREEN
)
var i = 0
while (
i < components.length
) {
val index = i
val check =
new JCheckBox(
components(index).name +
" [" +
components(index).category +
"]"
)
check.setFont(
new Font(
"Arial",
Font.PLAIN,
14
)
)
check.setForeground(TEXT)
check.setBackground(PANEL)
check.setFocusPainted(false)
check.setSelected(
selected(index)
)
check.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
selected(index) =
check.isSelected
selectedLabel.setText(
"Selected materials: " +
selectedCount()
)
}
}
)
materialBox.add(check)
i += 1
}
left.add(
materialScroll,
BorderLayout.CENTER
)
left.add(
selectedLabel,
BorderLayout.SOUTH
)
// ----------------------------------------------------------
// RIGHT PROJECT IDEA PANEL
// ----------------------------------------------------------
val right =
new JPanel()
right.setBackground(BG)
right.setLayout(
new BoxLayout(
right,
BoxLayout.Y_AXIS
)
)
right.add(
makeTitle(
"ENTER YOUR PROJECT IDEA",
21
)
)
right.add(
Box.createVerticalStrut(8)
)
right.add(
makeNormal(
"Example: smart light, robot, alarm, plant monitor..."
)
)
right.add(
Box.createVerticalStrut(10)
)
val projectInput =
new JTextArea()
projectInput.setFont(
new Font(
"Arial",
Font.PLAIN,
16
)
)
projectInput.setForeground(TEXT)
projectInput.setBackground(PANEL)
projectInput.setCaretColor(TEXT)
projectInput.setLineWrap(true)
projectInput.setWrapStyleWord(true)
val inputScroll =
new JScrollPane(
projectInput
)
inputScroll.setPreferredSize(
new Dimension(
500,
130
)
)
inputScroll.setMaximumSize(
new Dimension(
600,
150
)
)
right.add(inputScroll)
right.add(
Box.createVerticalStrut(15)
)
val generate =
makeButton(
"BIX-02 GENERATE PROJECTS"
)
generate.setMaximumSize(
new Dimension(
600,
55
)
)
right.add(generate)
right.add(
Box.createVerticalStrut(12)
)
val preview =
new JTextArea(
"Select materials and optionally enter\n" +
"a project idea.\n\n" +
"BIX-02 will generate a list of matching\n" +
"project ideas."
)
preview.setEditable(false)
preview.setLineWrap(true)
preview.setWrapStyleWord(true)
preview.setFont(
new Font(
"Arial",
Font.PLAIN,
14
)
)
preview.setForeground(MUTED)
preview.setBackground(PANEL)
right.add(
new JScrollPane(
preview
)
)
// ----------------------------------------------------------
// GENERATE
// ----------------------------------------------------------
generate.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
if (
selectedCount() == 0
) {
preview.setForeground(
ORANGE
)
preview.setText(
"Please select at least one material."
)
} else {
val idea =
projectInput.getText.trim
val result =
matchingProjects(idea)
if (
result.length == 0
) {
preview.setForeground(
ORANGE
)
preview.setText(
"No matching project was found.\n\n" +
"Try selecting Arduino UNO plus\n" +
"one or more sensors, outputs or motors."
)
} else {
switchPanel(
projectBrowserPanel(
idea,
result
)
)
}
}
}
}
)
// ----------------------------------------------------------
// CLEAR
// ----------------------------------------------------------
val clear =
makeButton("CLEAR")
clear.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
var j = 0
while (
j < selected.length
) {
selected(j) = false
j += 1
}
switchPanel(
createProjectPanel()
)
}
}
)
// ----------------------------------------------------------
// BACK
// ----------------------------------------------------------
val back =
makeButton("BACK")
back.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
switchPanel(
homePanel()
)
}
}
)
val buttons =
new JPanel(
new FlowLayout(
FlowLayout.LEFT
)
)
buttons.setBackground(BG)
buttons.add(clear)
buttons.add(back)
right.add(
Box.createVerticalStrut(10)
)
right.add(buttons)
// ----------------------------------------------------------
// MAIN
// ----------------------------------------------------------
val main =
new JPanel(
new GridLayout(
1,
2,
18,
0
)
)
main.setBackground(BG)
main.setBorder(
BorderFactory.createEmptyBorder(
10,
15,
10,
15
)
)
main.add(left)
main.add(right)
root.add(
main,
BorderLayout.CENTER
)
root
}
// ============================================================
// PROJECT SCORE
// ============================================================
def projectScore(
project: ProjectInfo,
idea: String
): Int = {
var score = 0
var i = 0
// Material matching
while (
i < project.required.length
) {
if (
hasComponent(
project.required(i)
)
) {
score += 10
}
i += 1
}
val q =
if (
idea == null
) {
""
} else {
idea.toLowerCase
}
val projectName =
project.name.toLowerCase
// English keywords
if (
q.contains("light") &&
projectName.contains("light")
) {
score += 35
}
if (
q.contains("lamp") &&
projectName.contains("lamp")
) {
score += 35
}
if (
q.contains("distance") &&
projectName.contains("distance")
) {
score += 35
}
if (
q.contains("parking") &&
projectName.contains("parking")
) {
score += 35
}
if (
q.contains("temperature") &&
projectName.contains("temperature")
) {
score += 35
}
if (
q.contains("humidity") &&
projectName.contains("temperature")
) {
score += 25
}
if (
q.contains("plant") &&
projectName.contains("plant")
) {
score += 35
}
if (
q.contains("soil") &&
projectName.contains("plant")
) {
score += 25
}
if (
q.contains("door") &&
projectName.contains("door")
) {
score += 35
}
if (
q.contains("motion") &&
projectName.contains("motion")
) {
score += 35
}
if (
q.contains("robot") &&
projectName.contains("robot")
) {
score += 35
}
if (
q.contains("bluetooth") &&
projectName.contains("bluetooth")
) {
score += 35
}
if (
q.contains("gas") &&
projectName.contains("gas")
) {
score += 35
}
if (
q.contains("counter") &&
projectName.contains("counter")
) {
score += 35
}
if (
q.contains("button") &&
projectName.contains("button")
) {
score += 35
}
if (
q.contains("temperature") &&
projectName.contains("temperature")
) {
score += 20
}
// Marathi keywords
if (
q.contains("??????") &&
projectName.contains("light")
) {
score += 30
}
if (
q.contains("????") &&
projectName.contains("lamp")
) {
score += 35
}
if (
q.contains("????") &&
projectName.contains("distance")
) {
score += 35
}
if (
q.contains("??????") &&
projectName.contains("temperature")
) {
score += 35
}
if (
q.contains("????????") &&
projectName.contains("temperature")
) {
score += 25
}
if (
q.contains("???") &&
projectName.contains("plant")
) {
score += 35
}
if (
q.contains("????") &&
projectName.contains("plant")
) {
score += 30
}
if (
q.contains("????") &&
projectName.contains("plant")
) {
score += 25
}
if (
q.contains("??????") &&
projectName.contains("door")
) {
score += 35
}
if (
q.contains("??????") &&
projectName.contains("motion")
) {
score += 35
}
if (
q.contains("?????") &&
projectName.contains("robot")
) {
score += 35
}
if (
q.contains("???") &&
projectName.contains("gas")
) {
score += 35
}
if (
q.contains("?????") &&
projectName.contains("counter")
) {
score += 35
}
score
}
// ============================================================
// MATCHING PROJECTS
// IMPORTANT:
// No variable named "match".
// "match" is a Scala reserved keyword.
// ============================================================
def matchingProjects(
idea: String
): Array[ProjectInfo] = {
val scoredProjects =
new ArrayList[ProjectInfo]()
val scores =
new ArrayList[Integer]()
var i = 0
while (
i < projects.length
) {
val currentProject =
projects(i)
val currentScore =
projectScore(
currentProject,
idea
)
if (
currentScore > 0
) {
scoredProjects.add(
currentProject
)
scores.add(
Integer.valueOf(
currentScore
)
)
}
i += 1
}
// ----------------------------------------------------------
// SORT BY SCORE
// ----------------------------------------------------------
var a = 0
while (
a < scores.size()
) {
var b =
a + 1
while (
b < scores.size()
) {
if (
scores.get(b).intValue() >
scores.get(a).intValue()
) {
val tempProject =
scoredProjects.get(a)
scoredProjects.set(
a,
scoredProjects.get(b)
)
scoredProjects.set(
b,
tempProject
)
val tempScore =
scores.get(a)
scores.set(
a,
scores.get(b)
)
scores.set(
b,
tempScore
)
}
b += 1
}
a += 1
}
// ----------------------------------------------------------
// BUILD RESULT
// ----------------------------------------------------------
val result =
new ArrayList[ProjectInfo]()
var k = 0
while (
k < scoredProjects.size() &&
k < 8
) {
result.add(
scoredProjects.get(k)
)
k += 1
}
// ----------------------------------------------------------
// FALLBACK:
// IF NO DIRECT KEYWORD MATCH EXISTS,
// FIND PROJECTS SHARING SELECTED MATERIALS.
// ----------------------------------------------------------
if (
result.size() == 0
) {
var pIndex = 0
while (
pIndex < projects.length &&
result.size() < 8
) {
val p =
projects(pIndex)
var hasMaterialMatch =
false
var cIndex = 0
while (
cIndex < p.required.length
) {
if (
hasComponent(
p.required(cIndex)
)
) {
hasMaterialMatch =
true
}
cIndex += 1
}
if (
hasMaterialMatch
) {
result.add(p)
}
pIndex += 1
}
}
result.toArray(
new Array[ProjectInfo](
result.size()
)
)
}
// ============================================================
// PROJECT BROWSER
// ============================================================
def projectBrowserPanel(
idea: String,
results: Array[ProjectInfo]
): JPanel = {
var currentIndex = 0
def buildScreen(): JPanel = {
val root =
makePanel()
root.setLayout(
new BorderLayout(
10,
10
)
)
val currentProject =
results(currentIndex)
root.add(
topBar(
"PROJECT " +
(currentIndex + 1) +
" / " +
results.length
),
BorderLayout.NORTH
)
// --------------------------------------------------------
// CONTENT
// --------------------------------------------------------
val content =
new JPanel(
new BorderLayout(
15,
10
)
)
content.setBackground(BG)
val robot =
new RobotPanel()
content.add(
robot,
BorderLayout.WEST
)
val right =
new JPanel()
right.setBackground(BG)
right.setLayout(
new BoxLayout(
right,
BoxLayout.Y_AXIS
)
)
// Project name
val name =
makeTitle(
"PROJECT " +
(currentIndex + 1) +
" ? " +
currentProject.name,
25
)
name.setForeground(BLUE)
right.add(name)
right.add(
Box.createVerticalStrut(8)
)
// Category
val category =
makeNormal(
"Category: " +
currentProject.category +
" Difficulty: " +
currentProject.difficulty
)
category.setForeground(GREEN)
right.add(category)
right.add(
Box.createVerticalStrut(7)
)
// Creator
right.add(
makeNormal(
"Creator / Database: " +
currentProject.creator
)
)
right.add(
Box.createVerticalStrut(5)
)
// Reference
right.add(
makeNormal(
"Reference: " +
currentProject.reference
)
)
right.add(
Box.createVerticalStrut(10)
)
// Description
val description =
new JTextArea(
currentProject.description
)
description.setEditable(false)
description.setLineWrap(true)
description.setWrapStyleWord(true)
description.setFont(
new Font(
"Arial",
Font.PLAIN,
15
)
)
description.setForeground(TEXT)
description.setBackground(BG)
right.add(description)
right.add(
Box.createVerticalStrut(10)
)
// --------------------------------------------------------
// TABS
// --------------------------------------------------------
val tabs =
new JTabbedPane()
tabs.setFont(
new Font(
"Arial",
Font.BOLD,
14
)
)
tabs.addTab(
"MATERIALS",
textTab(
materialText(
currentProject
)
)
)
tabs.addTab(
"WIRING",
textTab(
wiringText(
currentProject
)
)
)
tabs.addTab(
"STEPS",
textTab(
stepsText(
currentProject
)
)
)
tabs.addTab(
"HOW IT WORKS",
textTab(
currentProject.working +
"\n\n\nPROJECT USES\n\n" +
currentProject.uses
)
)
right.add(tabs)
content.add(
right,
BorderLayout.CENTER
)
root.add(
content,
BorderLayout.CENTER
)
// --------------------------------------------------------
// NAVIGATION
// --------------------------------------------------------
val navigation =
new JPanel(
new FlowLayout(
FlowLayout.CENTER,
8,
5
)
)
navigation.setBackground(BG)
val previous =
makeButton(
"< PREVIOUS PROJECT"
)
val next =
makeButton(
"NEXT PROJECT >"
)
val changeMaterials =
makeButton(
"CHANGE MATERIALS"
)
val home =
makeButton(
"HOME"
)
val counter =
makeNormal(
"PROJECT " +
(currentIndex + 1) +
" / " +
results.length
)
counter.setForeground(
ORANGE
)
previous.setEnabled(
currentIndex > 0
)
next.setEnabled(
currentIndex <
results.length - 1
)
// Previous
previous.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
if (
currentIndex > 0
) {
currentIndex -= 1
switchPanel(
buildScreen()
)
}
}
}
)
// Next
next.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
if (
currentIndex <
results.length - 1
) {
currentIndex += 1
switchPanel(
buildScreen()
)
}
}
}
)
// Change materials
changeMaterials.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
switchPanel(
createProjectPanel()
)
}
}
)
// Home
home.addActionListener(
new ActionListener {
def actionPerformed(
e: ActionEvent
): Unit = {
switchPanel(
homePanel()
)
}
}
)
navigation.add(previous)
navigation.add(counter)
navigation.add(next)
navigation.add(changeMaterials)
navigation.add(home)
root.add(
navigation,
BorderLayout.SOUTH
)
root
}
buildScreen()
}
// ============================================================
// RESULT TEXT
// ============================================================
def textTab(
value: String
): JScrollPane = {
val area =
new JTextArea(value)
area.setEditable(false)
area.setLineWrap(true)
area.setWrapStyleWord(true)
area.setFont(
new Font(
"Arial",
Font.PLAIN,
15
)
)
area.setForeground(TEXT)
area.setBackground(PANEL)
area.setBorder(
BorderFactory.createEmptyBorder(
18,
18,
18,
18
)
)
new JScrollPane(area)
}
// ============================================================
// MATERIAL TEXT
// ============================================================
def materialText(
project: ProjectInfo
): String = {
val sb =
new StringBuilder
sb.append(
"REQUIRED PROJECT MATERIALS\n"
)
sb.append(
"==========================\n\n"
)
var i = 0
while (
i < project.required.length
) {
sb.append(
(i + 1).toString
)
sb.append(
". "
)
sb.append(
project.required(i)
)
if (
hasComponent(
project.required(i)
)
) {
sb.append(
" [SELECTED BY YOU]"
)
}
sb.append("\n")
i += 1
}
sb.toString
}
// ============================================================
// WIRING TEXT
// ============================================================
def wiringText(
project: ProjectInfo
): String = {
val sb =
new StringBuilder
sb.append(
"BASIC WIRING GUIDE\n"
)
sb.append(
"==================\n\n"
)
sb.append(
"IMPORTANT:\n"
)
sb.append(
"Use the documentation and exact pinout\n"
)
sb.append(
"of your particular hardware module.\n\n"
)
var i = 0
while (
i < project.wiring.length
) {
sb.append(
(i + 1).toString
)
sb.append(
". "
)
sb.append(
project.wiring(i)
)
sb.append("\n")
i += 1
}
sb.toString
}
// ============================================================
// STEPS TEXT
// ============================================================
def stepsText(
project: ProjectInfo
): String = {
val sb =
new StringBuilder
sb.append(
"PROJECT BUILD STEPS\n"
)
sb.append(
"===================\n\n"
)
var i = 0
while (
i < project.steps.length
) {
sb.append(
"STEP "
)
sb.append(
(i + 1).toString
)
sb.append("\n")
sb.append(
project.steps(i)
)
sb.append("\n\n")
i += 1
}
sb.toString
}
// ============================================================
// START APPLICATION
// ============================================================
switchPanel(
loginPanel()
)
frame.setVisible(true)