Friday, December 12, 2025

Generative AI – Google Bard: A New Era of Intelligent Creativity

 

Generative AI – Google Bard: A New Era of Intelligent Creativity

Generative AI – Google Bard: A New Era of Intelligent Creativity


Generative Artificial Intelligence has reshaped how humans interact with machines, create digital content, and solve complex problems. Within this transformative wave, Google Bard stands out as a milestone innovation. Introduced as Google’s experimental conversational AI, Bard represents a dynamic blend of creativity, reasoning, and information retrieval. Built initially on LaMDA and later enhanced with Gemini, Bard has quickly become a key tool for writers, students, developers, and businesses. This article explores the evolution, features, working principles, and future potential of Generative AI through the lens of Google Bard.

1. Understanding Generative AI

Generative AI refers to artificial intelligence models capable of creating new content rather than merely analyzing or classifying data. These models can produce:

  • Text
  • Images
  • Code
  • Audio
  • Summaries
  • Structured data

Unlike traditional AI systems, which follow predefined patterns, generative models learn from massive datasets and use probabilistic reasoning to craft new outputs that resemble human creativity. Google Bard is an application of this technology in the domain of natural language generation and multimodal reasoning.

2. What Is Google Bard?

Google Bard is a conversational and generative AI chatbot designed to provide helpful, creative, and context-aware responses. Bard is capable of handling natural conversations, answering questions, summarizing information, writing content, and even generating computer code.

Over time, Bard has evolved from a simple experimental model to a powerful AI ecosystem integrated with Google’s search, productivity tools, and multimodal capabilities. With Gemini powering its intelligence, Bard has become more intuitive, reliable, and skilled in handling real-world tasks.

3. Evolution of Google Bard

a. LaMDA Phase

Bard was initially powered by LaMDA (Language Model for Dialogue Applications), which specialized in human-like conversational abilities. LaMDA focused on generating open-ended responses based on dialogue training, making Bard friendly and intuitive for everyday use.

b. PaLM 2 Enhancement

Later, Bard was upgraded to PaLM 2, enhancing its reasoning, coding, and multilingual abilities. This upgrade improved Bard’s performance in tasks like programming assistance, translation, and academic problem-solving.

c. Gemini Integration

The most significant leap came with the integration of Gemini, Google’s advanced multimodal model capable of understanding text, images, audio, and video. This enabled Bard to:

  • Analyze images
  • Generate diagrams
  • Handle complex queries
  • Understand contextual inputs
  • Engage in sophisticated multitask reasoning

Gemini transformed Bard into a versatile AI assistant for both personal and professional use.

4. How Google Bard Works

Bard operates using a combination of deep learning, neural networks, and vast training datasets. Its abilities are rooted in three pillars:

a. Natural Language Understanding

Bard interprets user queries by analyzing semantics, intent, tone, and context. This allows it to maintain coherent conversations and respond appropriately.

b. Generative Language Modeling

Based on the input, Bard predicts and generates the most meaningful sequence of words. This generative process ensures originality, clarity, and logical flow.

c. Multimodal Processing

With Gemini, Bard can process different types of input. For example, users can:

  • Upload an image and ask for analysis
  • Request visual explanations
  • Ask Bard to interpret charts, screenshots, or hand-written notes

This multimodal ability sets Bard apart from many traditional chatbots.

5. Key Features of Google Bard

1. Natural, Conversational Dialogue

Bard is designed to mimic natural human conversation. It adapts to the user’s style, intent, and tone, ensuring smooth interaction whether the user is casual, professional, or technical.

2. Creative Content Generation

Bard excels at generating:

  • Blogs and articles
  • Stories and poetry
  • Marketing content
  • Scripts and dialogues
  • Social media posts

It provides fresh, original ideas and can rewrite or refine user-generated text.

3. Coding and Debugging

Bard supports multiple programming languages, including Python, JavaScript, C++, and more. It can:

  • Write code from scratch
  • Explain code functionality
  • Debug programming errors
  • Optimize code for performance

4. Research and Information Retrieval

Bard integrates with Google Search to offer current, verifiable answers. This ensures responses are more accurate and up-to-date compared to static language models.

5. Multimodal Input Processing

Users can upload images, graphs, or documents for interpretation. Bard can extract text, summarize content, or provide insights based on the visual input.

6. Integration with Google Workspace

One of Bard’s strongest advantages is its compatibility with Google tools such as:

  • Gmail
  • Google Docs
  • Sheets
  • Slides
  • Drive

It can draft emails, create presentations, analyze spreadsheets, and organize files.

6. Applications of Google Bard

a. Education

Students use Bard for assignments, explanations, and study materials. It can simplify complex concepts, create revision notes, and generate project ideas.

b. Content Creation

Writers and marketers use Bard for brainstorming, drafting, SEO optimization, and social media content.

c. Business Productivity

Bard assists organizations by generating reports, automating documentation, analyzing data, and supporting customer queries.

d. Programming and Software Development

Developers leverage Bard for coding assistance, testing ideas, and accelerating software projects.

e. Research & Knowledge Discovery

Researchers use Bard to gather information, summarize research papers, and explore new scientific insights.

7. Advantages of Google Bard

  • Highly creative and flexible in generating diverse content
  • Google Search integration ensures accuracy and relevance
  • Multimodal capabilities support advanced reasoning
  • Fast, real-time responses
  • Strong coding and debugging support
  • Easy integration with workspace applications
  • Continuously improving with Gemini updates

8. Limitations and Considerations

Despite its power, Bard is not perfect:

  • It may occasionally generate incorrect or fabricated information (hallucinations)
  • Some advanced features may be limited by region
  • Performance can vary depending on model version and device
  • It requires user review for factual or sensitive content

Understanding these limitations helps users apply Bard more responsibly.

9. The Future of Google Bard and Generative AI

As Google continues to advance its Gemini models, Bard will likely evolve into a fully integrated AI system accessible across all Google products. The future may bring:

  • Real-time voice-to-voice AI conversations
  • Deeper personalization
  • AI-driven productivity automation
  • Enhanced reasoning and memory
  • Cross-application creativity tools

Generative AI is moving toward a collaborative ecosystem where humans and machines co-create. Bard represents a significant step in this journey.

Conclusion

Google Bard symbolizes the transformative potential of generative AI. With its powerful language abilities, multimodal understanding, and integration with Google’s ecosystem, Bard is not just a chatbot—it is a creative partner, knowledge assistant, and problem-solving companion. As the world enters a new era of intelligent automation, Bard continues to push boundaries, making AI more accessible, interactive, and impactful for everyone.

Thursday, December 11, 2025

Generative AI Prompt Text-to-Text: Introduction

 

Generative AI Prompt Text-to-Text: Introduction

Generative AI Prompt Text-to-Text


Generative Artificial Intelligence (AI) has rapidly transformed the way humans interact with machines. Among its many capabilities, text-to-text generation stands out as one of the most impactful, practical, and widely adopted applications. Whether it is drafting emails, summarizing long documents, writing code, answering customer queries, or creating marketing content, text-to-text models have become essential tools across industries. At the heart of this capability lies a simple but powerful mechanism: prompts. Prompts act as the instructions that guide the AI toward producing the desired output. Understanding how text-to-text generative AI works, and how prompts influence its behaviour, is crucial for anyone seeking to harness this technology effectively.

What is Text-to-Text Generative AI?

Text-to-text generative AI refers to models that take a text input and generate new text as output. Unlike traditional AI systems designed for narrow tasks like classification or keyword extraction, generative AI can produce original content that resembles human writing. These models are trained on massive datasets consisting of books, articles, code repositories, research papers, social media posts, and more. Through this training, they learn patterns, grammar, context, and even nuances of natural language.

A text-to-text model can handle a wide range of tasks using the same core architecture. For example:

  • Translating languages
  • Writing essays, poems, stories, or technical content
  • Summarizing long documents
  • Generating code
  • Answering questions
  • Rewriting or paraphrasing text
  • Filling missing information
  • Handling conversational queries in chatbots

This universality makes text-to-text generative AI one of the most versatile and accessible technologies available today.

How Prompts Drive Text-to-Text Generation

A prompt is any text you provide to a generative AI model. It acts as an instruction, description, or query that tells the model what kind of output you want. The model analyses the prompt’s structure, meaning, tone, and intent, and then generates content that aligns with it.

Prompts can be simple or detailed:

  • Simple prompt: “Write a summary of this paragraph.”
  • Detailed prompt: “Summarize the following article in under 150 words, highlighting the key arguments and maintaining a formal academic tone.”

The more precise and structured the prompt, the more accurate and relevant the AI’s output tends to be. This is why prompt engineering—crafting effective prompts—has emerged as an important skill.

Types of Prompts in Text-to-Text Systems

Generative AI prompts generally fall into several categories:

  1. Instructional Prompts
    These give the AI direct instructions, such as “Explain,” “Summarize,” “Translate,” or “Rewrite.”

  2. Contextual Prompts
    These include background information or data that the AI must consider.
    Example: Providing product details before asking for a marketing description.

  3. Few-Shot Prompts
    These include examples to guide the AI on the expected style or structure.

  4. Role-Based Prompts
    These assign a role to the AI, such as “Act as a professional tutor” or “Act as a content strategist.”

  5. Open-Ended Prompts
    Used for creative writing or brainstorming where there is no fixed answer.

Each type influences how the model interprets the request and what kind of output it generates.

How Text-to-Text Generative Models Work

Text-to-text models are primarily based on transformer architectures, which process language using attention mechanisms. These mechanisms allow the model to understand relationships between words, phrases, and sentences across the entire input.

The process generally involves the following steps:

  1. Input Processing:
    The model breaks the prompt into tokens (small text units).

  2. Context Understanding:
    It analyses the tokens and determines context, meaning, and relationships.

  3. Prediction:
    The model predicts the next token based on learned patterns and user instructions.

  4. Generation:
    It continues generating tokens sequentially until completing a coherent response.

Through extensive training, the model gains the capability to mimic human-like writing and provide meaningful, context-aware answers.

Why Text-to-Text AI Matters Today

Text-to-text generative AI has become important for several reasons:

1. Enhances Productivity

The ability to generate drafts, rewrite content, or produce summaries in seconds saves enormous time. Professionals across industries—from IT to marketing—use these tools to speed up workflows.

2. Democratizes Content Creation

Even individuals with limited writing or language skills can produce high-quality text using AI assistance. This levels the playing field for students, creators, entrepreneurs, and small businesses.

3. Improves Decision-Making

By generating concise summaries of complex documents, such as reports or research papers, AI helps users digest information faster and make informed decisions.

4. Supports Multilingual Communication

Text-to-text AI can translate and localize content instantly, bridging communication gaps across borders.

5. Enables Rapid Prototyping

Developers and innovators use text-to-text AI to generate code snippets, user stories, API documentation, and project ideas, accelerating the development process.

Applications of Text-to-Text Generative AI

The versatility of text-to-text AI has opened doors to countless applications, including:

Content Writing and Digital Marketing

Businesses use AI to create blog posts, social media captions, email newsletters, and product descriptions. The speed and consistency of AI-generated content improve marketing efficiency.

Education and E-Learning

Students and educators rely on text-to-text models for explanations, summaries, and study notes. AI tutors can provide personalized learning experiences at scale.

Customer Support

AI-driven chatbots and automated agents respond to customer queries quickly, offering improved support while reducing operational costs.

Programming and Software Development

Developers use AI to generate code, refactor existing programs, or explain complex logic. This accelerates software development cycles.

Research and Knowledge Work

Researchers use AI to gather, summarize, and reinterpret information from large datasets or academic materials.

Best Practices for Writing Effective Prompts

While text-to-text AI is powerful, the quality of output largely depends on the quality of prompts. Some best practices include:

  • Be clear and specific about what you want.
  • Include context or examples if the task requires a particular style.
  • Define the tone—formal, casual, technical, etc.
  • Set constraints, such as word count or format.
  • Avoid vague instructions, which can lead to irrelevant responses.

With practice, users can consistently generate accurate, meaningful, and high-quality output.

Conclusion

Generative AI text-to-text systems represent a major leap in digital communication, content creation, and automation. By converting simple prompts into rich textual output, they empower users to accomplish tasks faster, more creatively, and more efficiently. As technology continues to evolve, understanding how prompts work and how to use them effectively will become essential skills. The future of communication, creativity, and productivity is being shaped today by the capabilities of text-to-text generative AI, making it a transformative force across industries and everyday life.

Wednesday, December 10, 2025

How to Build a Simple, Secure VPN (WireGuard) — Explanation + Code

 

How to Build a Simple, Secure VPN (WireGuard) — Explanation + Code

Overview — what you’ll learn

This article explains how a Virtual Private Network (VPN) works at a high level and walks through building a lightweight, modern VPN using WireGuard. You’ll get the commands and configuration files to:

  • Generate keys for server and client
  • Configure a WireGuard server on a Linux VPS (Ubuntu/Debian)
  • Create a client configuration you can import to a phone or laptop
  • Configure IP forwarding and basic firewall rules
  • Test connectivity

Important legal note: A VPN can be used for legitimate privacy and networking purposes. Do not use it to break laws, violate terms of service, or commit wrongdoing. Always operate within local laws and your provider’s terms.

Quick primer: how VPNs work (short)

A VPN creates an encrypted tunnel between two endpoints: the client and the VPN server. When the tunnel is active, the client’s traffic is encapsulated and routed through the server, which can provide privacy, remote access to a private network, or allow your device to appear from the server’s network.

WireGuard is a modern, high-performance VPN protocol that’s simple to configure, uses modern cryptography, and is available in the Linux kernel (and on other platforms). That’s why we’ll use it here.

Requirements

  • A VPS with public IPv4 (Ubuntu 22.04 or Debian 12 recommended)
  • root or a user with sudo
  • Basic Linux command-line familiarity
  • WireGuard client app (available for Windows/macOS/Linux/Android/iOS)

Step 1 — Install WireGuard on the server

On Ubuntu/Debian:

# update and install
sudo apt update
sudo apt install -y wireguard iptables-persistent

iptables-persistent helps save firewall rules across reboots. On newer Ubuntu, you might prefer ufw — commands below will show both approaches.

Step 2 — Generate keys

WireGuard uses public/private key pairs. Create a directory for keys and generate them.

sudo mkdir -p /etc/wireguard/keys
sudo chmod 700 /etc/wireguard/keys
cd /etc/wireguard/keys

# server keys
wg genkey | tee server_private.key
 | wg pubkey > server_public.key

# client keys (example: client1)
wg genkey | tee client1_private.key
 | wg pubkey > client1_public.key

# show files (for copying to configs)
sudo cat server_private.key
sudo cat server_public.key
sudo cat client1_private.key
sudo cat client1_public.key

Store the private keys securely — only the owning machine needs them.

Step 3 — Server configuration

Create /etc/wireguard/wg0.conf and fill it like this. Replace placeholders (e.g., SERVER_PRIVATE_KEY, SERVER_PUBLIC_IP) with the actual values and IPs.

[Interface]
# Private key for server (from server_private.key)
PrivateKey = SERVER_PRIVATE_KEY
# VPN network address for the server
Address = 10.10.0.1/24
# Listen port for WireGuard
ListenPort = 51820
# Persist tun device across reboots (optional)
SaveConfig = true

# Example peer (client1)
[Peer]
# client's public key (client1_public.key)
PublicKey = CLIENT1_PUBLIC_KEY
# only allow client's VPN IP
 inside 10.10.0.0/24
AllowedIPs = 10.10.0.2/32

Save and set secure permissions:

sudo chmod 600 /etc/wireguard/wg0.conf

Step 4 — Enable IP forwarding & firewall (NAT)

Enable IP forwarding (temporary and persistent):

# temporary (until reboot)
sudo sysctl -w net.ipv4.ip_forward=1

# persistent
echo "net.ipv4.ip_forward=1" |
 sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Configure NAT so client traffic is masqueraded through the server’s public interface (assume eth0 is public interface — adjust if different):

Using iptables:

# enable NAT
sudo iptables -t nat -A 
POSTROUTING -o eth0 -j MASQUERADE

# accept forwarding from wg0
sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT

# save rules (Debian/Ubuntu)
sudo netfilter-persistent save

Using ufw (if you prefer):

# allow WireGuard UDP port
sudo ufw allow 51820/udp

# allow forwarding and NAT via 
/etc/ufw/before.rules
# (You must edit /etc/ufw/before.rules
 and add a NAT section as 
WireGuard docs suggest.)
# Then enable:
sudo ufw enable

Note: Confirm your VPS provider allows IP forwarding/NAT on their plan.

Step 5 — Start WireGuard

Bring up the interface:

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

# Check status
sudo wg show

wg show will display interface, 

listening port, and peers.

Step 6 — Create client configuration

Create a client config that your device will import (e.g., use client1_private.key and server public key).

client1.conf:

[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY
Address = 10.10.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = SERVER_PUBLIC_IP:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
  • Address is the VPN IP for the client.
  • AllowedIPs = 0.0.0.0/0 routes all traffic through the VPN (full-tunnel). If you only want to route specific subnets, set AllowedIPs accordingly (e.g., 10.10.0.0/24 for split-tunnel).

Transfer this .conf to your client device securely (e.g., SFTP or paste via secure channel). On mobile clients, WireGuard apps can scan a QR code to import the config.

You can generate a QR code on the server:

sudo apt install -y qrencode
qrencode -t ansiutf8 < client1.conf
# or produce PNG
qrencode -o client1.png < client1.conf

Step 7 — Add the client peer to the server (automate)

If you created the server config earlier without the client peer, you can add the peer dynamically:

# Example: add peer using wg (runtime) 
and persist using wg-quick save if 
SaveConfig=true
sudo wg set wg0 peer "$
(cat /etc/wireguard/keys/client1_public.key)" \
    allowed-ips 10.10.0.2/32

If SaveConfig=true in wg0.conf, you can then sudo wg-quick save wg0 to persist it.

Simple automation script (create client)

Here’s a small bash script to generate keys and produce a client config file:

#!/bin/bash
set -e
CLIENT_NAME=${1:-client1}
KEY_DIR=/etc/wireguard/keys
mkdir -p $KEY_DIR
cd $KEY_DIR

# generate keys
wg genkey | tee ${CLIENT_NAME}_private.key
 | wg pubkey > ${CLIENT_NAME}_public.key

SERVER_PUB=$(cat server_public.key)
CLIENT_PRIV=$(cat ${CLIENT_NAME}_private.key)
CLIENT_PUB=$(cat ${CLIENT_NAME}_public.key)

# variables - adapt to your network
SERVER_IP="YOUR_SERVER_PUBLIC_IP"
WG_NETWORK="10.10.0"
CLIENT_IP="${WG_NETWORK}.2/24"
WG_PORT=51820

cat > /etc/wireguard/${CLIENT_NAME}.conf <<EOF
[Interface]
PrivateKey = ${CLIENT_PRIV}
Address = ${CLIENT_IP}
DNS = 1.1.1.1

[Peer]
PublicKey = ${SERVER_PUB}
Endpoint = ${SERVER_IP}:${WG_PORT}
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
EOF

# add peer to server runtime
sudo wg set wg0 peer ${CLIENT_PUB}
 allowed-ips ${WG_NETWORK}.2/32

echo "Created /etc/wireguard/$
{CLIENT_NAME}.conf and added peer to wg0"

Run as root: sudo bash 

create-client.sh client2

Testing connectivity

  1. Import the client config into the WireGuard app.
  2. Activate the tunnel on the client.
  3. On the server: sudo wg show — you should see handshakes and data transfer bytes for the peer.
  4. On client, check public IP via https://ifconfig.co or curl ifconfig.co (should show server's public IP if full-tunnel).
  5. Test ping to server VPN IP: ping 10.10.0.1 from client.

Security best practices

  • Rotate keys if a private key is exposed.
  • Use a strong DNS provider or your own DNS resolver to avoid leaks.
  • Monitor logs for unfamiliar peers or traffic patterns.
  • Keep system packages and WireGuard up to date.
  • Limit which client IPs can access internal networks with AllowedIPs and firewall rules.

Troubleshooting tips

  • If wg show shows no handshake, ensure UDP port (51820) is allowed in VPS firewall and provider-level firewall.
  • Confirm sysctl net.ipv4.ip_forward is 1.
  • Verify NAT rules apply to the correct public interface (replace eth0 if your server uses a different name).
  • Use sudo tcpdump -n -i wg0 and -i eth0 to observe packets when debugging.

Alternatives & when to choose them

  • OpenVPN: older, feature-rich, more complex configuration; good for compatibility with legacy systems.
  • WireGuard: preferred for simplicity and performance for most modern use cases.

Final notes

This guide gives a compact, practical way to set up a minimal, secure WireGuard VPN server and client. Adapt IP ranges, firewall rules, and AllowedIPs to your needs. If you want, I can produce step-by-step instructions tailored to your VPS provider (e.g., DigitalOcean, AWS, Linode) or generate client configs for multiple devices — tell me the OS(es) or constraints and I’ll produce ready-to-import files.

Profit & Loss Calculator Android Studio Project

 


🚀 1. ANDROID APP VERSION (JAVA)

📱 Profit & Loss Calculator — Android Studio Project

Step 1: activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://
schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:padding="20dp"
    android:gravity="center"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/etCP"
        android:hint="Enter Cost Price"
        android:inputType="numberDecimal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <EditText
        android:id="@+id/etSP"
        android:hint="Enter Selling Price"
        android:inputType="numberDecimal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"/>

    <Button
        android:id="@+id/btnCalc"
        android:text="Calculate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"/>

    <TextView
        android:id="@+id/tvResult"
        android:text=""
        android:textSize="18sp"
        android:layout_marginTop="20dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

Step 2: MainActivity.java

package com.example.profitloss;

import androidx.appcompat.
app.AppCompatActivity;
import android.os.Bundle;
import android.widget.*;

public class MainActivity
 extends AppCompatActivity {

    EditText etCP, etSP;
    Button btnCalc;
    TextView tvResult;

    @Override
    protected void onCreate
(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        etCP = findViewById(R.id.etCP);
        etSP = findViewById(R.id.etSP);
        btnCalc = findViewById(R.id.btnCalc);
        tvResult = findViewById(R.id.tvResult);

        btnCalc.setOnClickListener(v -> {
            double cp = Double.
parseDouble(etCP.getText().toString());
            double sp = Double.
parseDouble(etSP.getText().toString());

            if (sp > cp) {
                double profit = sp - cp;
                double pp = profit / cp * 100;
                tvResult.setText("Profit:
 " + profit + "\nProfit %: " + pp);
            } else if (cp > sp) {
                double loss = cp - sp;
                double lp = loss / cp * 100;
                tvResult.setText("Loss: 
" + loss + "\nLoss %: " + lp);
            } else {
                tvResult.setText(
"No Profit No Loss");
            }
        });
    }
}

🎨 2. JavaFX GUI VERSION

Step 1: Main Application (Main.java)

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage stage) {
        TextField cpField = new TextField();
        cpField.setPromptText(
"Enter Cost Price");

        TextField spField = new TextField();
        spField.setPromptText(
"Enter Selling Price");

        Button calcBtn = new Button(
"Calculate");
        Label result = new Label();

        calcBtn.setOnAction(e -> {
            double cp = Double.
parseDouble(cpField.getText());
            double sp = Double.
parseDouble(spField.getText());

            if (sp > cp) {
                double profit = sp - cp;
                double percent =
 (profit / cp) * 100;
                result.setText(
"Profit: " + profit + " | " + percent + "%");
            } else if (cp > sp) {
                double loss = cp - sp;
                double percent = (
loss / cp) * 100;
                result.setText(
"Loss: " + loss + " | " + percent + "%");
            } else {
                result.setText(
"No Profit, No Loss");
            }
        });

        VBox root = new VBox(
10, cpField, spField, calcBtn, result);
        root.setPadding(new Insets(20));

        stage.setScene(new Scene(
root, 300, 250));
        stage.setTitle(
"Profit & Loss Calculator");
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

🌐 3. WEB VERSION (JSP + SERVLET)

Structure:

WebApp/
 ├── index.jsp
 ├── result.jsp
 └── ProfitLossServlet.java

Step 1: index.jsp

<!DOCTYPE html>
<html>
<body>
<h2>Profit & Loss Calculator</h2>

<form action="ProfitLossServlet" 
method="post">
    Cost Price: <input type="text"
 name="cp"><br><br>
    Selling Price: <input type="text" 
name="sp"><br><br>
    <input type="submit" value="Calculate">
</form>

</body>
</html>

Step 2: ProfitLossServlet.java

import jakarta.servlet.*;
import jakarta.servlet.http.*;
import java.io.IOException;

public class ProfitLossServlet 
extends HttpServlet {

    protected void doPost
(HttpServletRequest request,
 HttpServletResponse response)
            throws ServletException, 
IOException {

        double cp = 
Double.parseDouble(request.getParameter("cp"));
        double sp = 
Double.parseDouble(request.getParameter("sp"));

        String result;

        if (sp > cp) {
            double profit = sp - cp;
            double pp = profit / cp * 100;
            result = "Profit:
 " + profit + " ( " + pp + "% )";
        } else if (cp > sp) {
            double loss = cp - sp;
            double lp = loss / cp * 100;
            result = "Loss: " + loss 
+ " ( " + lp + "% )";
        } else {
            result = "No Profit No Loss";
        }

        request.setAttribute("result", 
result);
        RequestDispatcher rd = 
request.getRequestDispatcher("result.jsp");
        rd.forward(request, response);
    }
}

Step 3: result.jsp

<!DOCTYPE html>
<html>
<body>

<h2>Result</h2>
<p><b>${result}</b></p>

<a href="index.jsp">Go Back</a>

</body>
</html>

Spring Boot web app with MYSQL integration

 

1) Spring Boot (with REST & MySQL JPA)

Project type: Spring Boot (Maven).
Java version: 11+ recommended.

pom.xml (essential deps)

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>profitloss-service</artifactId>
  <version>1.0.0</version>

  <properties>
    <java.version>11</java.version>
    <spring.boot.version>3.1.0
</spring.boot.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot
</groupId>
      <artifactId>spring-boot-starter-web
</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot
</groupId>
      <artifactId>spring-boot-
starter-data-jpa</artifactId>
    </dependency>

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-
java</artifactId>
      <scope>runtime</scope>
    </dependency>

    <dependency>
      <groupId>org.springframework.
boot</groupId>
      <artifactId>spring-boot-
starter-validation</artifactId>
    </dependency>
    
    <dependency>
      <groupId>com.fasterxml.
jackson.core</groupId>
      <artifactId>jackson-
databind</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.
boot</groupId>
        <artifactId>spring-boot-
maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

src/main/resources/application.properties

Replace username/password/dbname with your MySQL values.

spring.datasource.url=jdbc:mysql:
//localhost:3306/profitlossdb?useSSL=
false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=yourpassword

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.
format_sql=true

server.port=8080

Domain: com.example.profitloss.model.Calculation.java

package com.example.profitloss.model;

import jakarta.persistence.*;
import java.time.Instant;

@Entity
public class Calculation {

    @Id
    @GeneratedValue(strategy =
 GenerationType.IDENTITY)
    private Long id;

    private double cp;
    private double sp;
    private double amount; // 
profit or loss magnitude
    private double percent;
    private boolean isProfit;
 // true -> profit, false -> 
loss (if equal, treat as neither)
    private Instant createdAt =
 Instant.now();

    // Constructors, getters, setters
    public Calculation() {}
    public Calculation(double cp,
 double sp, double amount, 
double percent, boolean isProfit) {
        this.cp = cp; this.sp = 
sp; this.amount = amount;
 this.percent = percent; this.isProfit = isProfit;
    }
    // getters and setters
 omitted for brevity (generate in IDE)
    // ...
    public Long getId(){return id;}
    public double getCp(){return cp;}
    public void setCp(double cp){this.cp=cp;}
    public double getSp(){return sp;}
    public void setSp(double sp){this.sp=sp;}
    public double getAmount(){return amount;}
    public void setAmount(double amt)
{this.amount=amt;}
    public double getPercent()
{return percent;}
    public void setPercent(double p)
{this.percent=p;}
    public boolean isProfit()
{return isProfit;}
    public void setProfit
(boolean profit){this.isProfit=profit;}
    public Instant getCreatedAt()
{return createdAt;}
    public void setCreatedAt
(Instant t){this.createdAt=t;}
}

Repository: CalculationRepository.java

package com.example.profitloss.repo;

import com.example.profitloss.
model.Calculation;
import org.springframework.data.
jpa.repository.JpaRepository;

public interface CalculationRepository 
extends JpaRepository<Calculation, Long> {}

DTO: CalculateRequest.java

package com.example.profitloss.dto;

import jakarta.validation.constraints.Min;

public class CalculateRequest {
    @Min(value = 0, message = 
"Cost price must be >= 0")
    private double cp;

    @Min(value = 0, message =
 "Selling price must be >= 0")
    private double sp;

    public double getCp(){return cp;}
    public void setCp(double cp){this.cp=cp;}
    public double getSp(){return sp;}
    public void setSp(double sp){this.sp=sp;}
}

Response DTO: CalculateResponse.java

package com.example.profitloss.dto;

public class CalculateResponse {
    private String type; // "profit",
"loss","no-profit-no-loss"
    private double amount;
    private double percent;
    private long id; // persisted 
record id (if saved)

    public CalculateResponse
(String type, double amount, 
double percent, long id){
        this.type = type; 
this.amount = amount; this.percent = 
percent; this.id = id;
    }
    // getters
    public String getType(){return type;}
    public double getAmount(){return amount;}
    public double getPercent(){return percent;}
    public long getId(){return id;}
}

Service: CalculationService.java

package com.example.profitloss.service;

import com.example.profitloss.
dto.CalculateRequest;
import com.example.profitloss.
model.Calculation;
import com.example.profitloss.
repo.CalculationRepository;
import org.springframework.
stereotype.Service;

@Service
public class CalculationService {

    private final CalculationRepository repo;

    public CalculationService
(CalculationRepository repo){
        this.repo = repo;
    }

    public Calculation calculateAndSave
(double cp, double sp){
        if (cp == sp) {
            Calculation calc = new 
Calculation(cp, sp, 0.0, 0.0, false);
            return repo.save(calc);
        }
        boolean isProfit = sp > cp;
        double amount = Math.abs(sp - cp);
        double percent = (amount / cp) * 100;
        Calculation calc = new 
Calculation(cp, sp, amount, percent, isProfit);
        return repo.save(calc);
    }
}

Controller (REST): CalculationController.java

package com.example.profitloss.controller;

import com.example.profitloss.
dto.CalculateRequest;
import com.example.profitloss.
dto.CalculateResponse;
import com.example.profitloss.
model.Calculation;
import com.example.profitloss.
service.CalculationService;
import jakarta.validation.Valid;
import org.springframework.http.
ResponseEntity;
import org.springframework.web.
bind.annotation.*;

@RestController
@RequestMapping("/api")
public class CalculationController {

    private final CalculationService service;

    public CalculationController
(CalculationService service){
        this.service = service;
    }

    // POST /api/calculate -> saves 
to DB and returns result
    @PostMapping("/calculate")
    public ResponseEntity<CalculateResponse>
 calculateAndSave(@Valid @RequestBody
 CalculateRequest req) {
        Calculation saved = service.
calculateAndSave(req.getCp(), req.getSp());
        String type;
        if (saved.getAmount() == 0.0) 
type = "no-profit-no-loss";
        else type = saved.isProfit() ?
 "profit" : "loss";
        CalculateResponse resp = new
 CalculateResponse(type, saved.getAmount(), 
saved.getPercent(), saved.getId());
        return ResponseEntity.ok(resp);
    }

    // GET /api/calculation/{id} -> 
fetch saved calculation
    @GetMapping("/calculation/{id}")
    public ResponseEntity<Calculation>
 getById(@PathVariable Long id) {
        return service.repo.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.
notFound().build());
    }
}

Note: For brevity service.repo was used in controller GET. In production extract via service method.

Application main

package com.example.profitloss;

import org.springframework.boot.
SpringApplication;
import org.springframework.boot.
autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ProfitlossServiceApplication {
    public static void main(String[] args){
        SpringApplication.run
(ProfitlossServiceApplication.class, args);
    }
}

How to run

  1. Start MySQL and create DB profitlossdb (or let JPA create; ensure user has privileges).
    Example:
    CREATE DATABASE profitlossdb;
    
  2. Update application.properties credentials.
  3. mvn spring-boot:run or build jar.

Example REST call (curl)

curl -X POST http://localhost:
8080/api/calculate \
 -H "Content-Type: application/json" \
 -d '{"cp":500,"sp":650}'

Response:

{"type":"profit","amount":
150.0,"percent":30.0,"id":1}

2) MySQL Integration (already included above)

  • JPA entity Calculation persists each calculation.
  • spring.jpa.hibernate.ddl-auto=update will create the table automatically.
  • You can query results via JPA repository or exposed REST endpoint.

If you want explicit SQL schema:

CREATE TABLE calculation (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  cp DOUBLE,
  sp DOUBLE,
  amount DOUBLE,
  percent DOUBLE,
  is_profit BOOLEAN,
  created_at TIMESTAMP DEFAULT
 CURRENT_TIMESTAMP
);

3) REST API (standalone description)

The Spring Boot app provides:

  • POST /api/calculate — accepts JSON { "cp": <number>, "sp": <number> } and returns { type, amount, percent, id }. Saves to DB.
  • GET /api/calculation/{id} — fetch saved record.

Validation: @Min(0) on input; add more error handling as needed.

4) Kotlin Android App (Android Studio)

Minimum: Android Gradle Plugin + Kotlin. Create new project (Empty Activity) and replace files.

res/layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:padding="24dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/etCP"
        android:hint="Cost Price (CP)"
        android:inputType="numberDecimal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <EditText
        android:id="@+id/etSP"
        android:hint="Selling Price (SP)"
        android:inputType="numberDecimal"
        android:layout_marginTop="12dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btnCalculate"
        android:text="Calculate"
        android:layout_marginTop="16dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/tvResult"
        android:textSize="18sp"
        android:layout_marginTop="18dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

MainActivity.kt

package com.example.profitlossapp

import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private lateinit var etCP: EditText
    private lateinit var etSP: EditText
    private lateinit var btnCalculate: Button
    private lateinit var tvResult: TextView

    override fun onCreate(savedInstanceState:
 Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        etCP = findViewById(R.id.etCP)
        etSP = findViewById(R.id.etSP)
        btnCalculate = findViewById
(R.id.btnCalculate)
        tvResult = findViewById(R.id.tvResult)

        btnCalculate.setOnClickListener {
            val cpText = etCP.text.
toString().trim()
            val spText = etSP.text.
toString().trim()
            if (cpText.isEmpty() || 
spText.isEmpty()) {
                tvResult.text = 
"Please enter both CP and SP."
                return@setOnClickListener
            }

            val cp = cpText.toDoubleOrNull()
            val sp = spText.toDoubleOrNull()
            if (cp == null || sp == null) {
                tvResult.text = 
"Invalid numbers."
                return@setOnClickListener
            }
            if (cp == 0.0) {
                tvResult.text = 
"CP cannot be zero for percentage calculation."
                return@setOnClickListener
            }

            when {
                sp > cp -> {
                    val profit = sp - cp
                    val percent = 
profit / cp * 100
                    tvResult.text =
 "Profit: %.2f\nProfit %%: %.2f".
format(profit, percent)
                }
                cp > sp -> {
                    val loss = cp - sp
                    val percent = 
loss / cp * 100
                    tvResult.text = 
"Loss: %.2f\nLoss %%: %.2f".format
(loss, percent)
                }
                else -> {
                    tvResult.text = 
"No Profit, No Loss."
                }
            }
        }
    }
}

Optional: Call Spring Boot REST from Android

  • Add Retrofit or OkHttp to build.gradle and POST to /api/calculate to persist results remotely.

Final notes & next steps

  • The Spring Boot project already includes REST endpoints and MySQL JPA integration — that covers items (1)-(3).
  • The Kotlin Android project is a simple UI app; it can be extended to call the REST API to persist calculations remotely.

Docker plus Docker Compose for Spring Boot app

 


Docker + Docker Compose for Spring Boot app

Kubernetes manifests (Deployment, Service, HorizontalPodAutoscaler, ConfigMap, Secret)

GitHub Actions CI/CD workflow (build, test, build Docker image, push to registry)

Android app updated to MVVM (Kotlin) with Retrofit integration and simple persistence

placeholders is the place where you must insert credentials (Docker registry, secrets). Copy/paste into your projects and adjust names/credentials.

Docker (Spring Boot)

Dockerfile

# Use a multi-stage build for a Spring 
Boot jar
FROM eclipse-temurin:17-jdk-jammy AS build
WORKDIR /app
COPY pom.xml mvnw ./
COPY .mvn .mvn
COPY src src
RUN ./mvnw -B -DskipTests package

FROM eclipse-temurin:17-jre-jammy
ARG JAR_FILE=target/*.jar
COPY --from=build /app/${JAR_FILE} 
/app/app.jar
EXPOSE 8080
ENTRYPOINT ["java","-Xms256m","
-Xmx512m","-jar","/app/app.jar"]

.dockerignore

target/
.vscode/
.idea/
*.iml
.mvn/wrapper/maven-wrapper.jar

docker-compose.yml (app + mysql)

version: "3.8"
services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: examplepassword
      MYSQL_DATABASE: profitlossdb
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql

  profitloss-app:
    build: .
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql
://mysql:3306/profitlossdb?useSSL=
false&serverTimezone=UTC
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: 
examplepassword
    depends_on:
      - mysql
    ports:
      - "8080:8080"

volumes:
  mysql-data:

Kubernetes manifests

Assume namespace profitloss. Secrets contain DB password and Docker registry creds — replace placeholders.

k8s/namespace.yaml

apiVersion: v1
kind: Namespace
metadata:
  name: profitloss

k8s/secret.yaml (DB password & optional registry)

apiVersion: v1
kind: Secret
metadata:
  name: profitloss-secret
  namespace: profitloss
type: Opaque
stringData:
  DB_PASSWORD: "examplepassword"        
   # replace
  REGISTRY_USERNAME: "your-registry-user" 
# replace if pushing private image
  REGISTRY_PASSWORD: "registry-pass"      
# replace

k8s/configmap.yaml (app config)

apiVersion: v1
kind: ConfigMap
metadata:
  name: profitloss-config
  namespace: profitloss
data:
  SPRING_DATASOURCE_URL: jdbc:mysql:
//profitloss-mysql:3306/profitlossdb?
useSSL=false&serverTimezone=UTC
  SPRING_DATASOURCE_USERNAME: root
  SPRING_JPA_HIBERNATE_DDL_AUTO: update

k8s/mysql-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: profitloss-mysql
  namespace: profitloss
spec:
  replicas: 1
  selector:
    matchLabels:
      app: profitloss-mysql
  template:
    metadata:
      labels:
        app: profitloss-mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: profitloss-secret
                  key: DB_PASSWORD
            - name: MYSQL_DATABASE
              value: profitlossdb
          ports:
            - containerPort: 3306
          volumeMounts:
            - name: mysql-data
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-data
          persistentVolumeClaim:
            claimName: mysql-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: profitloss
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 5Gi

k8s/app-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: profitloss-app
  namespace: profitloss
spec:
  replicas: 2
  selector:
    matchLabels:
      app: profitloss-app
  template:
    metadata:
      labels:
        app: profitloss-app
    spec:
      containers:
        - name: profitloss-app
          image: your-registry/profitloss
-service:latest   # replace with built image
          imagePullPolicy: IfNotPresent
          env:
            - name: SPRING_DATASOURCE_URL
              valueFrom:
                configMapKeyRef:
                  name: profitloss-config
                  key: SPRING_DATASOURCE_URL
            - name: SPRING_DATASOURCE_USERNAME
              valueFrom:
                configMapKeyRef:
                  name: profitloss-config
                  key:
 SPRING_DATASOURCE_USERNAME
            - name: SPRING_DATASOURCE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: profitloss-secret
                  key: DB_PASSWORD
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: profitloss-service
  namespace: profitloss
spec:
  selector:
    app: profitloss-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

k8s/hpa.yaml (autoscale)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: profitloss-hpa
  namespace: profitloss
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: profitloss-app
  minReplicas: 2
  maxReplicas: 6
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60

Optional: add Ingress manifest depending on your cluster.

GitHub Actions — CI/CD

This workflow:

  • Runs tests
  • Builds jar
  • Builds Docker image
  • Logs into Docker registry (Docker Hub/GitHub Packages)
  • Pushes image
  • Optionally applies Kubernetes manifests via kubectl (if you configure KUBE_CONFIG)

Create .github/workflows/ci-cd.yml:

name: CI/CD Pipeline

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

env:
  IMAGE_NAME: your-registry/profitloss-service

jobs:
  build-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 17

      - name: Build and run tests
        run: ./mvnw -B clean verify

  build-and-push:
    needs: build-test
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Login to registry
        uses: docker/login-action@v2
        with:
          registry: docker.io
          username: ${{ secrets.
DOCKERHUB_USERNAME }}   # set in repo secrets
          password: ${{ secrets.
DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v4
        with:
          context: .
          push: true
          tags: ${{ env.IMAGE_NAME }}:latest

  deploy-k8s:
    needs: build-and-push
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup kubectl
        uses: azure/setup-kubectl@v3
        with:
          version: 'latest'

      - name: Configure kubectl
        run: |
          echo "${{ secrets.KUBE_CONFIG }}" 
> kubeconfig
          export KUBECONFIG=$PWD/kubeconfig

      - name: Update image in deployment
 (kubectl set image)
        run: |
          kubectl -n profitloss set 
image deployment/profitloss-app 
profitloss-app=${{ env.IMAGE_NAME }}
:latest || true
          kubectl -n profitloss
 rollout status deployment/
profitloss-app --timeout=120s || true

Secrets to add in repo settings

  • DOCKERHUB_USERNAME, DOCKERHUB_TOKEN (or GitHub Packages token)
  • KUBE_CONFIG — base64 encoded kubeconfig or raw kubeconfig contents (use caution)

Android — MVVM architecture (Kotlin)

I’ll provide a minimal, clean MVVM structure with Retrofit + LiveData + ViewModel + Repository.

Gradle dependencies (app/build.gradle)

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdk 34
    defaultConfig {
        applicationId "com.example.
profitlossapp"
        minSdk 21
        targetSdk 34
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    implementation "org.jetbrains.
kotlin:kotlin-stdlib:1.9.0"
    implementation 'androidx.core:
core-ktx:1.12.0'
    implementation 'androidx.
appcompat:appcompat:1.6.1'
    implementation 'com.google.
android.material:material:1.9.0'
    implementation 'androidx.
lifecycle:lifecycle-livedata-ktx:2.6.2'
    implementation 'androidx.
lifecycle:lifecycle-viewmodel-ktx:2.6.2'
    implementation 'com.
squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.
squareup.retrofit2:converter-gson:2.9.0'
    implementation 
'org.jetbrains.kotlinx:
kotlinx-coroutines-android:1.7.3'
}

Network layer (Retrofit)

network/ProfitLossApi.kt

package com.example.profitlossapp.network

import com.example.
profitlossapp.model.CalculateRequest
import com.example.
profitlossapp.model.CalculateResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST

interface ProfitLossApi {
    @POST("/api/calculate")
    suspend fun calculate
(@Body req: CalculateRequest): 
Response<CalculateResponse>
}

network/RetrofitClient.kt

package com.example.profitlossapp.network

import retrofit2.Retrofit
import retrofit2.converter.
gson.GsonConverterFactory

object RetrofitClient {
    private const val BASE_URL = 
"http://10.0.2.2:8080" // emulator -> host

    val api: ProfitLossApi by lazy {
        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory
(GsonConverterFactory.create())
            .build()
            .create
(ProfitLossApi::class.java)
    }
}

Models

model/CalculateRequest.kt

package com.example.profitlossapp.model
data class CalculateRequest(val cp: 
Double, val sp: Double)

model/CalculateResponse.kt

package com.example.profitlossapp.model
data class CalculateResponse(val type:
 String, val amount: Double, 
val percent: Double, val id: Long)

Repository

repository/ProfitLossRepository.kt

package com.example.profitlossapp.repository

import com.example.profitlossapp.
model.CalculateRequest
import com.example.profitlossapp.
model.CalculateResponse
import com.example.profitlossapp.
network.RetrofitClient
import retrofit2.Response

class ProfitLossRepository {
    suspend fun calculate(req: 
CalculateRequest): Response<CalculateResponse> {
        return RetrofitClient.
api.calculate(req)
    }
}

ViewModel

ui/MainViewModel.kt

package com.example.profitlossapp.ui

import androidx.lifecycle.*
import com.example.profitlossapp.
model.CalculateRequest
import com.example.profitlossapp.
model.CalculateResponse
import com.example.profitlossapp.
repository.ProfitLossRepository
import kotlinx.coroutines.launch

class MainViewModel : ViewModel() {

    private val repo = ProfitLossRepository()

    private val _result = 
MutableLiveData<CalculateResponse?>()
    val result: 
LiveData<CalculateResponse?> = _result

    private val _error = 
MutableLiveData<String?>()
    val error: LiveData<String?> = _error

    fun calculate(cp: Double, sp: Double) {
        viewModelScope.launch {
            try {
                val response =
 repo.calculate(CalculateRequest(cp, sp))
                if (response.isSuccessful) {
                    _result.value = 
response.body()
                    _error.value = null
                } else {
                    _error.value =
 "Server error: ${response.code()}"
                }
            } catch (e: Exception) {
                _error.value = e.message
            }
        }
    }
}

UI (Activity)

ui/MainActivity.kt

package com.example.profitlossapp.ui

import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import androidx.activity.viewModels
import androidx.appcompat.
app.AppCompatActivity
import com.example.profitlossapp.R

class MainActivity : AppCompatActivity() {
    private val vm:
 MainViewModel by viewModels()

    override fun 
onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val etCP =
 findViewById<EditText>(R.id.etCP)
        val etSP = 
findViewById<EditText>(R.id.etSP)
        val btn =
 findViewById<Button>(R.id.btnCalculate)
        val tv =
 findViewById<TextView>(R.id.tvResult)

        btn.setOnClickListener {
            val cp =
 etCP.text.toString().toDoubleOrNull()
            val sp =
 etSP.text.toString().toDoubleOrNull()
            if (cp == 
null || sp == null) {
                tv.text = "Enter valid numbers"
                return@setOnClickListener
            }
            vm.calculate(cp, sp)
        }

        vm.result.observe(this) { resp ->
            resp?.let {
                tv.text = 
"Type: ${it.type}\nAmount:
 ${it.amount}\nPercent:
 ${it.percent}\nID: ${it.id}"
            }
        }

        vm.error.observe(this) { err ->
            err?.let { tv.text = "Error: $it" }
        }
    }
}

Layout (res/layout/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:padding="24dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText android:id="@+id/etCP" 
android:hint="Cost Price" 
android:inputType="numberDecimal" 
android:layout_width="match_parent" 
android:layout_height="wrap_content"/>
    <EditText android:id="@+id/etSP"
 android:hint="Selling Price" 
android:inputType="numberDecimal"
 android:layout_marginTop="12dp"
 android:layout_width="match_parent" 
android:layout_height="wrap_content"/>
    <Button android:id="@+id/btnCalculate" 
android:text="Calculate" 
android:layout_marginTop="16dp" 
android:layout_width="match_parent"
 android:layout_height="wrap_content"/>
    <TextView android:id="@+id/tvResult" 
android:textSize="16sp" 
android:layout_marginTop="18dp" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content"/>
</LinearLayout>

Quick instructions & notes

  • Docker: docker build -t your-registry/profitloss-service:latest . then docker push ... (or use the GitHub Actions workflow).
  • Docker Compose: docker compose up --build
  • Kubernetes: kubectl apply -f k8s/namespace.yaml && kubectl apply -f k8s/secret.yaml && kubectl apply -f k8s/configmap.yaml && kubectl apply -f k8s/mysql-deployment.yaml && kubectl apply -f k8s/app-deployment.yaml && kubectl apply -f k8s/hpa.yaml
  • GitHub Actions: set repository secrets (DOCKERHUB_USERNAME, DOCKERHUB_TOKEN, KUBE_CONFIG).
  • Android MVVM: run emulator and ensure Spring Boot is reachable — use 10.0.2.2 for the emulator or your machine IP for a real device. Allow CORS on Spring Boot if calling from other origins (add @CrossOrigin to controller or CorsFilter).

Class-Based Java Program (Object-Oriented)

 

Class-Based Java Program (Object-Oriented)



1. Class-Based Java Program (Object-Oriented)

class ProfitLoss {

    private double cp;
    private double sp;

    public ProfitLoss(double cp, double sp) {
        this.cp = cp;
        this.sp = sp;
    }

    public void calculate() {
        if (sp > cp) {
            double profit = sp - cp;
            double profitPercent = 
(profit / cp) * 100;
            System.out.println(
"Profit: " + profit);
            System.out.println(
"Profit Percentage: " + profitPercent + "%");

        } else if (cp > sp) {
            double loss = cp - sp;
            double lossPercent = 
(loss / cp) * 100;
            System.out.println
("Loss: " + loss);
            System.out.println
("Loss Percentage: " + lossPercent + "%");

        } else {
            System.out.println
("No Profit, No Loss.");
        }
    }
}

public class ProfitLossMain {
    public static void main(String[] args) {
        ProfitLoss obj = 
new ProfitLoss(500, 650);
        obj.calculate();
    }
}

2. Menu-Driven Console Version

(Choose 1 for profit/loss, 2 to exit)

import java.util.Scanner;

public class ProfitLossMenu {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int choice;

        do {
            System.out.println("\n
===== PROFIT & LOSS CALCULATOR =====");
            System.out.println("1.
 Calculate Profit / Loss");
            System.out.println("2. Exit");
            System.out.print("Enter
 your choice: ");
            choice = sc.nextInt();

            switch (choice) {

                case 1:
                    System.out.print
("Enter Cost Price (CP): ");
                    double cp = 
sc.nextDouble();

                    System.out.print
("Enter Selling Price (SP): ");
                    double sp = 
sc.nextDouble();

                    if (sp > cp) {
                        double profit = 
sp - cp;
                        double profitPercent
 = (profit / cp) * 100;
                        System.out.println
("Profit: " + profit);
                        System.out.println
("Profit Percentage: " + profitPercent + "%");

                    } else if (cp > sp) {
                        double loss = cp - sp;
                        double lossPercent 
= (loss / cp) * 100;
                        System.out.println
("Loss: " + loss);
                        System.out.println
("Loss Percentage: " + lossPercent + "%");

                    } else {
                        System.out.println
("No Profit, No Loss.");
                    }
                    break;

                case 2:
                    System.out.println
("Exiting...");
                    break;

                default:
                    System.out.println
("Invalid Choice! Try again.");
            }

        } while (choice != 2);

        sc.close();
    }
}

3. GUI Version (Java Swing)

This version shows a small graphical window for input and output.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ProfitLossGUI extends JFrame {

    private JTextField cpField, spField;
    private JButton btnCalculate;
    private JLabel resultLabel;

    public ProfitLossGUI() {
        setTitle("Profit & Loss Calculator");
        setSize(350, 250);
        setDefaultCloseOperation
(JFrame.EXIT_ON_CLOSE);
        setLayout(new GridLayout(4, 2));

        add(new JLabel("Cost Price (CP): "));
        cpField = new JTextField();
        add(cpField);

        add(new JLabel("Selling Price (SP): "));
        spField = new JTextField();
        add(spField);

        btnCalculate = new JButton
("Calculate");
        add(btnCalculate);

        resultLabel = new JLabel("");
        add(resultLabel);

        btnCalculate.
addActionListener(new ActionListener() {
            public void
 actionPerformed(ActionEvent e) {
                double cp = 
Double.parseDouble(cpField.getText());
                double sp = 
Double.parseDouble(spField.getText());

                if (sp > cp) {
                    double profit = sp - cp;
                    double profitPer
 = (profit / cp) * 100;
                    resultLabel.setText
("Profit: " + profit + " 
| " + profitPer + "%");

                } else if (cp > sp) {
                    double loss = cp - sp;
                    double lossPer = 
(loss / cp) * 100;
                    resultLabel.
setText("Loss: " + loss + " | " 
+ lossPer + "%");

                } else {
                    resultLabel.
setText("No Profit, No Loss.");
                }
            }
        });

        setVisible(true);
    }

    public static void main(String[] args) {
        new ProfitLossGUI();
    }
}

🎉 All Versions Completed

You now have: ✔ Simple Java Program
✔ OOP/Class-based Program
✔ Menu-driven Console Program
✔ GUI Program using Swing

How to Build Your Own VPN (WireGuard)

 


Free Guide: How to Build Your Own VPN (WireGuard)

Free Guide: How to Build Your Own VPN (WireGuard)


This expanded tutorial combines:



✔ Step-by-step VPS provider guides (DigitalOcean, AWS, Linode, Vultr,

 Hostinger)
✔ Multiple client configuration files
✔ Automation scripts
✔ Code samples
✔ Security best practices
✔ Troubleshooting

1. Introduction – What Is a VPN and Why Build Your Own?

A Virtual Private Network (VPN) creates an encrypted tunnel between a device and a remote server. When connected, all internet traffic travels through this tunnel, hiding your real IP address and protecting your data from snooping, surveillance, and insecure networks.

Most users rely on commercial VPN apps, but building your own VPN has several advantages:

  • No third-party logging risks — only you control traffic
  • Faster speeds because of zero user-sharing congestion
  • Fixed static IP for remote development, SSH access, or hosting
  • Learning experience in networking, tunneling, encryption, and Linux

This guide will use WireGuard, a modern VPN protocol designed for simplicity and high performance.

2. Why WireGuard?

WireGuard has become popular because:

  • It uses state-of-the-art cryptography
  • It is extremely lightweight
  • The configuration is simple and readable
  • It provides better speed and stability than OpenVPN/IPSec

A typical WireGuard configuration consists of:

  • A server with a public IP
  • One or more clients (Windows, Android, iOS, Linux, macOS)
  • A pair of keys (private/public) for each device

3. System Requirements

You need:

  • A VPS (any provider) with a public IPv4
  • Ubuntu 22.04 or Debian 12 (recommended)
  • Root or sudo privileges
  • WireGuard client apps for your devices

4. Installing WireGuard on Linux Server

Update packages

sudo apt update && sudo apt upgrade -y

Install WireGuard

sudo apt install -y wireguard 
iptables-persistent

A network interface named wg0 will be created later in configuration.

5. Generating Server & Client Keys

Create a secure folder:

sudo mkdir -p /etc/wireguard/keys
sudo chmod 700 /etc/wireguard/keys
cd /etc/wireguard/keys

Generate server keys

wg genkey | tee server_
private.key | wg pubkey > server_public.key

Generate one client key (client1)

wg genkey | tee client1_private.key 
| wg pubkey > client1_public.key

6. Creating the WireGuard Server Configuration

Create:

sudo nano /etc/wireguard/wg0.conf

Paste:

[Interface]
PrivateKey = SERVER_PRIVATE_KEY
Address = 10.10.0.1/24
ListenPort = 51820
SaveConfig = true

[Peer]
PublicKey = CLIENT1_PUBLIC_KEY
AllowedIPs = 10.10.0.2/32

Replace:

  • SERVER_PRIVATE_KEY → content of server_private.key
  • CLIENT1_PUBLIC_KEY → content of client1_public.key

Secure:

sudo chmod 600 /etc/wireguard/wg0.conf

7. Enable IP Forwarding & NAT

Temporary forwarding

sudo sysctl -w net.ipv4.ip_forward=1

Permanent forwarding

echo "net.ipv4.ip_forward=1" | 
sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Enable NAT

Assume your public interface is eth0:

sudo iptables -t nat -A POSTROUTING
 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i wg0 -j ACCEPT
sudo iptables -A FORWARD -o wg0 -j ACCEPT
sudo netfilter-persistent save

8. Start the VPN Server

sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0

Check status:

sudo wg show

9. Creating the Client Configuration File

Create client1.conf:

[Interface]
PrivateKey = CLIENT1_PRIVATE_KEY
Address = 10.10.0.2/24
DNS = 1.1.1.1

[Peer]
PublicKey = SERVER_PUBLIC_KEY
Endpoint = YOUR.SERVER.IP:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Use the WireGuard app (Windows, macOS, Android, iOS) to import the .conf.

10. Automation Script: Create New Clients Easily

Create:

sudo nano /usr/local/bin/wg-add-client

Paste:

#!/bin/bash

NAME=$1
WG_DIR="/etc/wireguard"
KEY_DIR="$WG_DIR/keys"

wg genkey | tee $KEY_DIR
/${NAME}_private.key 
| wg pubkey > $KEY_DIR
/${NAME}_public.key

SERVER_PUB=$(cat $KEY_DIR
/server_public.key)
CLIENT_PRIV=$(cat $KEY_DIR
/${NAME}_private.key)
CLIENT_PUB=$(cat $KEY_DIR
/${NAME}_public.key)

cat <<EOF > $WG_DIR/${NAME}.conf
[Interface]
PrivateKey = ${CLIENT_PRIV}
Address = 10.10.0.10/24
DNS = 1.1.1.1

[Peer]
PublicKey = ${SERVER_PUB}
Endpoint = YOUR.SERVER.IP:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF

wg set wg0 peer ${CLIENT_PUB}
 allowed-ips 
10.10.0.10/32
echo "Client $NAME created."

Make executable:

sudo chmod +x /usr/local/bin/wg-add-client

Use:

sudo wg-add-client client2

11. Provider-Specific Setup Guides

DigitalOcean

  1. Create a Droplet → Ubuntu 22.04
  2. Allow UDP 51820 under firewall
  3. Follow this guide normally
  4. Use Droplet public IP in Endpoint=

AWS EC2

  1. Launch Ubuntu EC2 instance
  2. In Security Groups, allow UDP 51820
  3. Disable Source/Dest Check (for NAT)
  4. Add an Elastic IP (optional)

Linode / Akamai

  1. Create Ubuntu Linode
  2. Check "Firewall" → allow UDP 51820
  3. Configure NAT rules

Vultr

  1. Deploy Ubuntu 22.04
  2. Under "Firewall" allow UDP 51820
  3. Add NAT

Hostinger VPS

  1. Create VPS instance
  2. Use panel to enable "Open Ports"
  3. Install WireGuard normally

12. Client Setup Instructions

Windows

  1. Install WireGuard from the official site
  2. Click → Add Tunnel → Import From File
  3. Select client1.conf

macOS

  1. Install WireGuard from App Store
  2. Import config

Linux

sudo wg-quick up client1

Android / iOS

  1. Install app from Play Store/App Store
  2. Tap "+" → Import from file or QR code

13. Testing Your VPN

Ping

ping 10.10.0.1

Check IP

curl ifconfig.me

You should now appear from your server’s IP.

14. Security Best Practices

  • Rotate keys every few months
  • Disable unused clients
  • Limit AllowedIPs for internal devices
  • Use strong DNS (Cloudflare / Quad9)
  • Keep the OS updated

15. Troubleshooting

No handshake?

  • UDP 51820 blocked
  • Wrong public/private keys
  • NAT rules missing

No internet inside VPN?

  • Missing MASQUERADE rule
  • Incorrect interface name (eth0 vs ens3)

Mobile clients disconnecting?

Set:

PersistentKeepalive = 25

16. Conclusion

Congratulations — you now have a fully working, secure, self-hosted VPN using WireGuard. You can add unlimited devices, automate client creation, or expand your VPN into a multi-region network with multiple servers.

Generative AI – Google Bard: A New Era of Intelligent Creativity

  Generative AI – Google Bard: A New Era of Intelligent Creativity Generative Artificial Intelligence has reshaped how humans interact wit...