Code Sketch
kundali
Category: Programming
import javax.swing._
import java.awt._
import java.awt.event._
import java.awt.geom._
import scala.util.Random
// ============================================================
// KUNDALI PURAN - FULL SINGLE FILE SCALA SWING APP
// ============================================================
val frame = new JFrame("Kundali Puran - Divine Astrology")
frame.setSize(1150, 780)
frame.setResizable(false)
val root = new JPanel(new BorderLayout())
root.setBackground(new Color(8, 10, 28))
// ============================================================
// ANIMATED BACKGROUND
// ============================================================
val background = new JPanel() {
val rnd = new Random(12345)
val starsX = Array.fill(180)(rnd.nextInt(1150))
val starsY = Array.fill(180)(rnd.nextInt(780))
val starsSize = Array.fill(180)(1 + rnd.nextInt(3))
val starsSpeed = Array.fill(180)(0.2 + rnd.nextDouble() * 1.2)
var angle = 0.0
var pulse = 0.0
var moonX = -100.0
setOpaque(true)
override def paintComponent(g: Graphics): Unit = {
super.paintComponent(g)
val g2 = g.asInstanceOf[Graphics2D]
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
)
val w = getWidth
val h = getHeight
// --------------------------------------------------------
// BACKGROUND GRADIENT
// --------------------------------------------------------
val gradient = new GradientPaint(
0,
0,
new Color(7, 9, 30),
w,
h,
new Color(35, 12, 62)
)
g2.setPaint(gradient)
g2.fillRect(0, 0, w, h)
// --------------------------------------------------------
// STARS
// --------------------------------------------------------
var i = 0
while (i < starsX.length) {
val alpha =
(130 + 100 * Math.abs(Math.sin(pulse + i * 0.17))).toInt
g2.setColor(
new Color(
255,
235,
150,
Math.max(50, Math.min(255, alpha))
)
)
g2.fillOval(
starsX(i),
starsY(i),
starsSize(i),
starsSize(i)
)
i += 1
}
// --------------------------------------------------------
// BIG COSMIC GLOW
// --------------------------------------------------------
val cx = w / 2
val cy = h / 2
var r = 330
while (r > 40) {
val alpha = (2 + (340 - r) / 25)
g2.setColor(
new Color(
255,
190,
60,
Math.min(25, alpha)
)
)
g2.drawOval(
cx - r,
cy - r,
r * 2,
r * 2
)
r -= 20
}
// --------------------------------------------------------
// ORBIT RINGS
// --------------------------------------------------------
g2.setStroke(new BasicStroke(1.2f))
var ring = 110
while (ring <= 310) {
g2.setColor(
new Color(
255,
200,
80,
45
)
)
g2.drawOval(
cx - ring,
cy - ring,
ring * 2,
ring * 2
)
ring += 40
}
// --------------------------------------------------------
// MOVING PLANET
// --------------------------------------------------------
val px =
cx + Math.cos(angle) * 250
val py =
cy + Math.sin(angle) * 150
g2.setColor(new Color(100, 150, 255, 50))
g2.fillOval(
(px - 28).toInt,
(py - 28).toInt,
56,
56
)
g2.setColor(new Color(110, 170, 255))
g2.fillOval(
(px - 12).toInt,
(py - 12).toInt,
24,
24
)
// --------------------------------------------------------
// GOLDEN ORB
// --------------------------------------------------------
val orbPulse =
75 + (Math.sin(pulse) * 8).toInt
g2.setColor(
new Color(
255,
190,
60,
35
)
)
g2.fillOval(
cx - orbPulse,
cy - orbPulse,
orbPulse * 2,
orbPulse * 2
)
// --------------------------------------------------------
// DECORATIVE LOTUS
// --------------------------------------------------------
val lotusY = h - 75
g2.setColor(new Color(255, 190, 80, 120))
var p = 0
while (p < 7) {
val lx =
cx + (p - 3) * 28
val path = new Path2D.Double()
path.moveTo(lx, lotusY)
path.curveTo(
lx - 20,
lotusY - 20,
lx - 18,
lotusY - 45,
lx,
lotusY - 55
)
path.curveTo(
lx + 18,
lotusY - 45,
lx + 20,
lotusY - 20,
lx,
lotusY
)
g2.fill(path)
p += 1
}
// --------------------------------------------------------
// UPDATE ANIMATION
// --------------------------------------------------------
angle += 0.012
pulse += 0.045
moonX += 0.6
if (moonX > w + 100) {
moonX = -100
}
}
}
background.setLayout(null)
// ============================================================
// TITLE
// ============================================================
val title = new JLabel(
"<html><center><font color='#FFD76A' size='6'>? KUNDALI PURAN ?</font><br>" +
"<font color='#FFF1B0' size='3'>Divine Astrology ? Rashi ? Cosmic Guidance</font></center></html>",
SwingConstants.CENTER
)
title.setBounds(190, 20, 770, 105)
title.setOpaque(false)
background.add(title)
// ============================================================
// MAIN CARD
// ============================================================
val card = new JPanel()
card.setLayout(null)
card.setBackground(new Color(15, 14, 40, 235))
card.setBorder(
BorderFactory.createLineBorder(
new Color(255, 205, 90),
2
)
)
card.setBounds(85, 135, 980, 555)
background.add(card)
// ============================================================
// FORM TITLE
// ============================================================
val formTitle = new JLabel(
"? Enter Your Birth Details ?",
SwingConstants.CENTER
)
formTitle.setForeground(new Color(255, 220, 120))
formTitle.setFont(new Font("Serif", Font.BOLD, 27))
formTitle.setBounds(235, 18, 510, 45)
card.add(formTitle)
// ============================================================
// LABEL FUNCTION
// ============================================================
def makeLabel(
text: String,
x: Int,
y: Int
): JLabel = {
val l = new JLabel(text)
l.setForeground(new Color(245, 235, 210))
l.setFont(new Font("SansSerif", Font.BOLD, 15))
l.setBounds(x, y, 180, 30)
card.add(l)
l
}
// ============================================================
// TEXT FIELD FUNCTION
// ============================================================
def makeField(
x: Int,
y: Int,
width: Int
): JTextField = {
val f = new JTextField()
f.setFont(new Font("SansSerif", Font.PLAIN, 16))
f.setForeground(new Color(30, 25, 45))
f.setBackground(new Color(250, 245, 230))
f.setBorder(
BorderFactory.createLineBorder(
new Color(220, 170, 70),
1
)
)
f.setBounds(x, y, width, 35)
card.add(f)
f
}
// ============================================================
// FORM FIELDS
// ============================================================
makeLabel("First Name", 55, 85)
val firstName = makeField(220, 82, 250)
makeLabel("Surname", 55, 135)
val surname = makeField(220, 132, 250)
makeLabel("Birth Date", 55, 185)
val birthDate = makeField(220, 182, 250)
birthDate.setToolTipText("Example: 15/08/2010")
makeLabel("Birth Time", 55, 235)
val birthTime = makeField(220, 232, 250)
birthTime.setToolTipText("Example: 14:30")
makeLabel("Birth Place", 55, 285)
val birthPlace = makeField(220, 282, 250)
// ============================================================
// RIGHT SIDE INFORMATION
// ============================================================
val infoBox = new JTextArea()
infoBox.setEditable(false)
infoBox.setLineWrap(true)
infoBox.setWrapStyleWord(true)
infoBox.setFont(new Font("Serif", Font.PLAIN, 16))
infoBox.setForeground(new Color(255, 239, 185))
infoBox.setBackground(new Color(25, 20, 55))
infoBox.setBorder(
BorderFactory.createTitledBorder(
BorderFactory.createLineBorder(
new Color(255, 200, 80),
1
),
" ? Kundali Preview ? ",
0,
0,
new Font("Serif", Font.BOLD, 16),
new Color(255, 210, 100)
)
)
infoBox.setText(
"\n Welcome to Kundali Puran.\n\n" +
" Enter your birth details and press\n" +
" GENERATE KUNDALI.\n\n" +
" The application will show:\n\n" +
" ? Rashi\n" +
" ? Rashi symbol\n" +
" ? Element\n" +
" ? Planet association\n" +
" ? Traditional deity association\n" +
" ? Lucky number\n" +
" ? General guidance\n\n" +
" Note: This is a traditional,\n" +
" entertainment-style astrology reading."
)
infoBox.setBounds(520, 82, 410, 295)
card.add(infoBox)
// ============================================================
// STATUS
// ============================================================
val status = new JLabel(
"? Ready to generate your Kundali"
)
status.setForeground(new Color(150, 240, 180))
status.setFont(new Font("SansSerif", Font.BOLD, 14))
status.setBounds(520, 395, 410, 30)
card.add(status)
// ============================================================
// RESULT DATA
// ============================================================
case class AstroInfo(
rashi: String,
symbol: String,
element: String,
planet: String,
deity: String,
lucky: Int,
nature: String,
guidance: String
)
// ============================================================
// RASHI FUNCTION
// ============================================================
def getRashi(day: Int, month: Int): AstroInfo = {
if ((month == 3 && day >= 21) || (month == 4 && day <= 19)) {
AstroInfo(
"Mesha (Aries)",
"?",
"Agni",
"Mangal",
"Shri Hanuman",
9,
"Energetic, direct and courageous",
"Focus your energy on useful goals and avoid rushing decisions."
)
} else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) {
AstroInfo(
"Vrishabha (Taurus)",
"?",
"Prithvi",
"Shukra",
"Maa Lakshmi",
6,
"Patient, practical and steady",
"Consistency and patience can help you move toward your goals."
)
} else if ((month == 5 && day >= 21) || (month == 6 && day <= 20)) {
AstroInfo(
"Mithuna (Gemini)",
"?",
"Vayu",
"Budha",
"Shri Ganesha",
5,
"Curious, communicative and adaptable",
"Learning and communication can become important strengths."
)
} else if ((month == 6 && day >= 21) || (month == 7 && day <= 22)) {
AstroInfo(
"Karka (Cancer)",
"?",
"Jala",
"Chandra",
"Shiva",
2,
"Caring, emotional and intuitive",
"Balance emotions with practical thinking."
)
} else if ((month == 7 && day >= 23) || (month == 8 && day <= 22)) {
AstroInfo(
"Simha (Leo)",
"?",
"Agni",
"Surya",
"Surya Dev",
1,
"Confident, expressive and warm",
"Leadership is useful when combined with patience and listening."
)
} else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) {
AstroInfo(
"Kanya (Virgo)",
"?",
"Prithvi",
"Budha",
"Shri Ganesha",
5,
"Analytical, organized and thoughtful",
"Small consistent improvements can produce strong results."
)
} else if ((month == 9 && day >= 23) || (month == 10 && day <= 22)) {
AstroInfo(
"Tula (Libra)",
"?",
"Vayu",
"Shukra",
"Maa Lakshmi",
6,
"Balanced, social and diplomatic",
"Consider different viewpoints before making important choices."
)
} else if ((month == 10 && day >= 23) || (month == 11 && day <= 21)) {
AstroInfo(
"Vrishchika (Scorpio)",
"?",
"Jala",
"Mangal",
"Shri Hanuman",
9,
"Focused, determined and intense",
"Use determination constructively and give yourself time to reflect."
)
} else if ((month == 11 && day >= 22) || (month == 12 && day <= 21)) {
AstroInfo(
"Dhanu (Sagittarius)",
"?",
"Agni",
"Guru",
"Shri Vishnu",
3,
"Optimistic, adventurous and curious",
"Exploration and learning may open new possibilities."
)
} else if ((month == 12 && day >= 22) || (month == 1 && day <= 19)) {
AstroInfo(
"Makara (Capricorn)",
"?",
"Prithvi",
"Shani",
"Shani Dev",
8,
"Disciplined, patient and responsible",
"Steady effort is more useful than trying to do everything at once."
)
} else if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) {
AstroInfo(
"Kumbha (Aquarius)",
"?",
"Vayu",
"Shani",
"Shani Dev",
8,
"Independent, inventive and thoughtful",
"New ideas can grow when combined with practical planning."
)
} else {
AstroInfo(
"Meena (Pisces)",
"?",
"Jala",
"Guru",
"Shri Vishnu",
3,
"Imaginative, compassionate and intuitive",
"Creativity and kindness can be valuable strengths."
)
}
}
// ============================================================
// LUCKY NUMBER
// ============================================================
def calculateNumber(
name: String,
day: Int,
month: Int,
year: Int
): Int = {
var total = day + month + year
var i = 0
while (i < name.length) {
total += name.charAt(i).toInt
i += 1
}
while (total > 9) {
var sum = 0
var n = total
while (n > 0) {
sum += n % 10
n = n / 10
}
total = sum
}
if (total == 0) 1 else total
}
// ============================================================
// GENERATE BUTTON
// ============================================================
val generateButton = new JButton(
"? GENERATE KUNDALI ?"
)
generateButton.setFont(
new Font("SansSerif", Font.BOLD, 16)
)
generateButton.setForeground(Color.WHITE)
generateButton.setBackground(
new Color(170, 90, 25)
)
generateButton.setFocusPainted(false)
generateButton.setBounds(70, 355, 400, 50)
card.add(generateButton)
// ============================================================
// CLEAR BUTTON
// ============================================================
val clearButton = new JButton(
"CLEAR"
)
clearButton.setFont(
new Font("SansSerif", Font.BOLD, 14)
)
clearButton.setForeground(Color.WHITE)
clearButton.setBackground(
new Color(70, 55, 100)
)
clearButton.setFocusPainted(false)
clearButton.setBounds(70, 420, 190, 45)
card.add(clearButton)
// ============================================================
// EXIT BUTTON
// ============================================================
val exitButton = new JButton(
"EXIT"
)
exitButton.setFont(
new Font("SansSerif", Font.BOLD, 14)
)
exitButton.setForeground(Color.WHITE)
exitButton.setBackground(
new Color(85, 45, 60)
)
exitButton.setFocusPainted(false)
exitButton.setBounds(280, 420, 190, 45)
card.add(exitButton)
// ============================================================
// GENERATE ACTION
// ============================================================
generateButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
val nameText =
firstName.getText.trim
val surnameText =
surname.getText.trim
val dateText =
birthDate.getText.trim
val timeText =
birthTime.getText.trim
val placeText =
birthPlace.getText.trim
if (
nameText.isEmpty ||
surnameText.isEmpty ||
dateText.isEmpty ||
timeText.isEmpty ||
placeText.isEmpty
) {
JOptionPane.showMessageDialog(
frame,
"Please fill all birth details.",
"Missing Details",
JOptionPane.WARNING_MESSAGE
)
} else {
val dateParts =
dateText.split("/")
val timeParts =
timeText.split(":")
if (
dateParts.length != 3 ||
timeParts.length != 2
) {
JOptionPane.showMessageDialog(
frame,
"Use Date: DD/MM/YYYY\nUse Time: HH:MM",
"Invalid Format",
JOptionPane.ERROR_MESSAGE
)
} else {
try {
val day =
dateParts(0).toInt
val month =
dateParts(1).toInt
val year =
dateParts(2).toInt
val hour =
timeParts(0).toInt
val minute =
timeParts(1).toInt
if (
day < 1 ||
day > 31 ||
month < 1 ||
month > 12 ||
year < 1900 ||
year > 2100 ||
hour < 0 ||
hour > 23 ||
minute < 0 ||
minute > 59
) {
JOptionPane.showMessageDialog(
frame,
"Please enter a valid date and time.",
"Invalid Details",
JOptionPane.ERROR_MESSAGE
)
} else {
status.setText(
"? Reading cosmic information..."
)
status.setForeground(
new Color(255, 220, 100)
)
generateButton.setEnabled(false)
val timer =
new javax.swing.Timer(
900,
null
)
timer.addActionListener(
new ActionListener {
override def actionPerformed(
ev: ActionEvent
): Unit = {
timer.stop()
val astro =
getRashi(day, month)
val fullName =
nameText + " " + surnameText
val lucky =
calculateNumber(
fullName,
day,
month,
year
)
val sb =
new StringBuilder
sb.append("\n")
sb.append(
" ? YOUR KUNDALI ?\n"
)
sb.append("\n")
sb.append(
" Name : "
)
sb.append(fullName)
sb.append("\n")
sb.append(
" Birth : "
)
sb.append(dateText)
sb.append(" ")
sb.append(timeText)
sb.append("\n")
sb.append(
" Place : "
)
sb.append(placeText)
sb.append("\n\n")
sb.append(
" RASHI : "
)
sb.append(astro.rashi)
sb.append(" ")
sb.append(astro.symbol)
sb.append("\n")
sb.append(
" Element : "
)
sb.append(astro.element)
sb.append("\n")
sb.append(
" Planet : "
)
sb.append(astro.planet)
sb.append("\n")
sb.append(
" Deity : "
)
sb.append(astro.deity)
sb.append("\n")
sb.append(
" Lucky No. : "
)
sb.append(lucky)
sb.append("\n\n")
sb.append(
" NATURE\n"
)
sb.append(
" "
)
sb.append(astro.nature)
sb.append("\n\n")
sb.append(
" GENERAL GUIDANCE\n"
)
sb.append(
" "
)
sb.append(astro.guidance)
sb.append("\n\n")
sb.append(
" ? DEVACHA HATH - Traditional association\n"
)
sb.append(
" According to this simple rashi-based reading,\n"
)
sb.append(
" the traditional deity association is: "
)
sb.append(astro.deity)
sb.append("\n\n")
sb.append(
" ? This reading is for traditional/entertainment\n"
)
sb.append(
" purposes and is not a scientific prediction."
)
infoBox.setText(
sb.toString
)
status.setText(
"? Kundali generated successfully"
)
status.setForeground(
new Color(130, 255, 170)
)
generateButton.setEnabled(true)
}
}
)
timer.setRepeats(false)
timer.start()
}
} catch {
case _: NumberFormatException =>
JOptionPane.showMessageDialog(
frame,
"Date and time must contain numbers only.\n\nExample:\n15/08/2010\n14:30",
"Invalid Input",
JOptionPane.ERROR_MESSAGE
)
}
}
}
}
}
)
// ============================================================
// CLEAR ACTION
// ============================================================
clearButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
firstName.setText("")
surname.setText("")
birthDate.setText("")
birthTime.setText("")
birthPlace.setText("")
infoBox.setText(
"\n Welcome to Kundali Puran.\n\n" +
" Enter your birth details and press\n" +
" GENERATE KUNDALI.\n\n" +
" The application will show:\n\n" +
" ? Rashi\n" +
" ? Rashi symbol\n" +
" ? Element\n" +
" ? Planet association\n" +
" ? Traditional deity association\n" +
" ? Lucky number\n" +
" ? General guidance\n\n" +
" Note: This is a traditional,\n" +
" entertainment-style astrology reading."
)
status.setText(
"? Ready to generate your Kundali"
)
status.setForeground(
new Color(150, 240, 180)
)
}
}
)
// ============================================================
// EXIT ACTION
// ============================================================
exitButton.addActionListener(
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
frame.dispose()
}
}
)
// ============================================================
// ANIMATION TIMER
// ============================================================
val animationTimer =
new javax.swing.Timer(
35,
new ActionListener {
override def actionPerformed(
e: ActionEvent
): Unit = {
background.repaint()
}
}
)
animationTimer.start()
// ============================================================
// ADD EVERYTHING
// ============================================================
root.add(
background,
BorderLayout.CENTER
)
frame.setContentPane(root)
frame.setLocationRelativeTo(null)
// ============================================================
// IMPORTANT: DIRECT STARTUP
// ============================================================
SwingUtilities.invokeLater(
new Runnable {
override def run(): Unit = {
frame.setVisible(true)
frame.toFront()
frame.requestFocus()
}
}
)