Hi Friends,

Even as I launch this today ( my 80th Birthday ), I realize that there is yet so much to say and do. There is just no time to look back, no time to wonder,"Will anyone read these pages?"

With regards,
Hemen Parekh
27 June 2013

Now as I approach my 90th birthday ( 27 June 2023 ) , I invite you to visit my Digital Avatar ( www.hemenparekh.ai ) – and continue chatting with me , even when I am no more here physically

Thursday, 17 July 2025

ChatGPT writes Source Codes For OnLineJobsFair Portal

 






I asked ChatGPT to write Source Codes for the following :

Software Architecture For Online Jobs Fair..  29 March 2018




ChatGPT  came up with the following :


Excellent! This is one of the most comprehensive modular breakdowns of a recruitment platform I’ve seen — especially with your early foresight in 2018. Let’s proceed module-wise, using modern open-source tools, AI/NLP frameworks, and microservice-friendly design.


✅ STRUCTURE OF IMPLEMENTATION

I'll deliver this in stages, each covering:

  1. Module Name & Purpose

  2. Updated Tech Stack

  3. Key APIs/Endpoints

  4. Sample Source Code (Python/FastAPI + React + MongoDB)

  5. AI/NLP Enhancements if applicable


🔹STAGE 1 — EMPLOYER ZONE


1. Business Registration

📌 Purpose: Register companies and recruiters with a unique Employer ID.

🔧 Stack:

  • Backend: Python (FastAPI)

  • Frontend: React + TailwindCSS

  • DB: MongoDB

🔑 API Endpoints:

  • POST /api/employer/register

  • GET /api/employer/{employer_id}

📄 Source Code (FastAPI - simplified)

python
from fastapi import FastAPI, HTTPException from pydantic import BaseModel from uuid import uuid4 import pymongo client = pymongo.MongoClient("mongodb://localhost:27017/") db = client["jobsfair"] employers = db["employers"] app = FastAPI() class Employer(BaseModel): company_name: str contact_person: str email: str phone: str industry: str @app.post("/api/employer/register") def register_employer(data: Employer): employer_id = str(uuid4()) employer_data = data.dict() employer_data["employer_id"] = employer_id employers.insert_one(employer_data) return {"employer_id": employer_id, "status": "Registered"}

2. Job Postings + Résumé Match Engine

📌 Purpose: Post jobs and receive AI-ranked candidate matches.

🔧 Added Stack:

  • Resume Matching: spaCy / HuggingFace Transformers

  • Job Matching Index: cosine similarity of embeddings (e.g., Sentence-BERT)

📄 Key Code Snippet (Resume-JD Similarity)

python
from sentence_transformers import SentenceTransformer, util model = SentenceTransformer('all-MiniLM-L6-v2') def compute_match_score(job_description: str, resume_text: str): jd_embed = model.encode(job_description, convert_to_tensor=True) res_embed = model.encode(resume_text, convert_to_tensor=True) score = util.pytorch_cos_sim(jd_embed, res_embed).item() return round(score * 100, 2) # Percentage match

📄 FastAPI Endpoint

python
@app.post("/api/job/post") def post_job(job: JobPosting): job_id = str(uuid4()) job_data = job.dict() job_data["job_id"] = job_id db.jobs.insert_one(job_data) # Find best matches resumes = list(db.resumes.find({})) matches = [] for resume in resumes: score = compute_match_score(job_data["description"], resume["text"]) matches.append((resume["candidate_id"], score)) matches.sort(key=lambda x: x[1], reverse=True) return {"job_id": job_id, "top_matches": matches[:10]}

3. Résumé Search + Grabber

📌 Purpose: Filter & access résumé pool including cross-employer uploads.

🔧 Added Stack:

  • Search Engine: Apache SOLR or Elasticsearch

  • Resume Parser: Python + pdfminer.six / docx / Tika

📄 SOLR/Elasticsearch Integration (pseudo-code)

python
def search_resumes_by_skills(skills): query = { "query": { "bool": { "should": [{"match": {"skills": skill}} for skill in skills], "minimum_should_match": 1 } } } results = elasticsearch.search(index="resumes", body=query) return results["hits"]["hits"]

4. Employer Payment Account

📌 Purpose: Handle billing for paid services like Online Job Fair.

🔧 Tech Additions:

  • Stripe or Razorpay integration

  • Wallet balance, invoice logs, credit usage tracking

📄 API Flow:

  • /api/payment/create-account

  • /api/payment/charge

  • /api/payment/history

📄 Stripe Sample (Python)

python
import stripe stripe.api_key = "sk_test_..." @app.post("/api/payment/charge") def charge_employer(employer_id: str, amount: float): employer = employers.find_one({"employer_id": employer_id}) if not employer: raise HTTPException(status_code=404) # Stripe checkout (simplified) intent = stripe.PaymentIntent.create( amount=int(amount * 100), # cents currency='inr', receipt_email=employer["email"] ) return {"client_secret": intent.client_secret}

🔜 NEXT STAGE PREVIEW

Coming Up:

  • Jobseeker Zone (Candidate Registration, Job Search, Resume Update Alerts)

  • Online Job Fair (Live video rooms, whiteboard, STT questions)

  • Value Add Services (Resume Parser, Rater, Interview QnA DB)


Would you like me to:

  1. Continue with the Jobseeker Zone module next?

  2. Bundle each zone into a full GitHub-style repository structure?

  3. Generate mock UI dashboards for Jobseeker side too?

Let’s go step-by-step. Your call!


STAGE 2 — JOBSEEKER ZONE


1. Candidate Registration

📌 Purpose: Let freshers and professionals register their profiles (optionally via LinkedIn).

🔧 Stack:

  • Backend: FastAPI

  • Frontend: React

  • DB: MongoDB

  • LinkedIn OAuth: using authlib or Firebase Auth

🔑 API Endpoints:

  • POST /api/candidate/register

  • POST /api/candidate/linkedin-auth

  • GET /api/candidate/{id}

📄 FastAPI Code (Freshers vs Experienced)

python
from pydantic import BaseModel from typing import Optional class Candidate(BaseModel): name: str email: str phone: str experience_years: Optional[int] = 0 key_skills: list[str] linkedin_url: Optional[str] = None is_fresher: Optional[bool] = True @app.post("/api/candidate/register") def register_candidate(data: Candidate): candidate_id = str(uuid4()) data_dict = data.dict() data_dict["candidate_id"] = candidate_id db.candidates.insert_one(data_dict) return {"candidate_id": candidate_id, "status": "Registered"}

💡 LinkedIn Autofill Option: Use LinkedIn API to fetch profile, then pre-fill the form using JavaScript fetch or Firebase Auth.


2. Candidate Job Search

📌 Purpose: Show personalized job results based on profile match (AI-driven).

🔧 Additions:

  • Job-candidate match via cosine similarity (like before)

  • Auto-fill search filters based on candidate profile

  • Fast text search via SOLR/Elasticsearch

📄 FastAPI Job Search Endpoint

python
@app.get("/api/jobs/search") def search_jobs(candidate_id: str, override_skills: Optional[str] = None): candidate = db.candidates.find_one({"candidate_id": candidate_id}) if not candidate: raise HTTPException(status_code=404) skills = override_skills.split(',') if override_skills else candidate['key_skills'] jobs = list(db.jobs.find({})) # Fetch all jobs results = [] for job in jobs: score = compute_match_score(" ".join(skills), job["description"]) results.append((job["job_id"], job["title"], score)) results.sort(key=lambda x: x[2], reverse=True) return {"results": results[:10]}

3. Résumé Update Notification

📌 Purpose: Automatically notify candidates to update outdated resumes.

🔧 Stack Additions:

  • Email automation via SendGrid or SMTP

  • Triggering parser if resume is old or unmatched

📄 Trigger Notification Function

python
from datetime import datetime, timedelta @app.post("/api/resume/check-update") def check_resume_update(candidate_id: str): candidate = db.candidates.find_one({"candidate_id": candidate_id}) resume_date = candidate.get("last_updated") if resume_date and datetime.now() - resume_date > timedelta(days=90): send_update_email(candidate["email"]) return {"status": "Update suggested via email"} return {"status": "Resume is up-to-date"} def send_update_email(email): # Simplified email logic import smtplib server = smtplib.SMTP("smtp.gmail.com", 587) message = "Please update your resume to improve match visibility!" server.sendmail("admin@onlinejobsfair.com", email, message)

4. UI Mockup Suggestions (Jobseeker Dashboard)

We can generate these visually next if needed:

  • Welcome Panel (shows match score, alerts)

  • Job Recommendations List (with match %

  • Profile Completion Tracker

  • Resume Upload / Parser Keyword Review


5. NLP Skill Extraction (Optional Enhancement)

Use keyword extraction from uploaded résumé to pre-populate skills.

📄 Skill Extractor using spaCy

python
import spacy nlp = spacy.load("en_core_web_sm") def extract_skills_from_resume(resume_text: str): doc = nlp(resume_text) return [chunk.text.lower() for chunk in doc.noun_chunks if chunk.text.lower() in SKILL_SET]

Where SKILL_SET = set of known tech/soft skills scraped or curated from job data.

===========================================

STAGE 3 — ONLINE JOB FAIR MODULE


✅ OVERVIEW

Components:

  1. Video Interviews (live, real-time panel)

  2. Candidate Assessment Forms (rating + remarks)

  3. Speech-to-Text Conversion of Interview Questions

  4. Interactive Whiteboard for Coding/Notes

Modern Stack Suggestions:

FunctionRecommended Stack / Tool
Video Interview100ms / Agora / Jitsi Meet + WebRTC
STT Conversion[Whisper API (OpenAI)] or Vosk – local Python STT
WhiteboardExcalidraw / Ziteboard embeddable
Assessment FormsFastAPI backend + MongoDB for storing structured ratings
Frontend UIReact + TailwindCSS + WebSockets for live events

1. 🔴 VIDEO INTERVIEWS (Live with multi-user panel)

🔧 Option 1: Embed Jitsi Meet (Open-source & Free)
🔧 Option 2: Use 100ms or Agora SDK (paid but scalable with mobile support)

📄 Basic Jitsi Integration in React (Frontend)

jsx
import { useEffect } from 'react'; const VideoRoom = ({ roomName }) => { useEffect(() => { const domain = "meet.jit.si"; const options = { roomName: roomName, width: "100%", height: 600, parentNode: document.getElementById("jitsi-container"), configOverwrite: {}, interfaceConfigOverwrite: {}, }; const api = new window.JitsiMeetExternalAPI(domain, options); return () => api.dispose(); }, [roomName]); return <div id="jitsi-container" />; }; export default VideoRoom;

2. 📝 CANDIDATE ASSESSMENT FORM

📌 Functionality:

  • Each interviewer fills a form

  • Fields: Communication, Technical, Attitude, Final Rating

  • Stored & aggregated per candidate

📄 MongoDB Schema

json
{ "interview_id": "uuid", "candidate_id": "uuid", "interviewer_id": "uuid", "scores": { "technical": 7, "communication": 8, "problem_solving": 6 }, "final_rating": 7, "comments": "Good candidate but needs to improve system design.", "timestamp": "ISO_DATE" }

📄 FastAPI Endpoint

python
class Assessment(BaseModel): interview_id: str candidate_id: str interviewer_id: str scores: dict final_rating: int comments: str @app.post("/api/assessment/submit") def submit_assessment(data: Assessment): db.assessments.insert_one(data.dict()) return {"status": "Saved"}

3. 🗣️ SPEECH-TO-TEXT (STT) FOR INTERVIEW QUESTIONS

🧠 Suggestion:

  • Use Whisper (OpenAI) for high accuracy

  • Alternate: Vosk for offline inference

📄 Whisper API Example (Python)

python
import openai openai.api_key = "your-api-key" def transcribe_audio(audio_path): with open(audio_path, "rb") as f: transcript = openai.Audio.transcribe("whisper-1", f) return transcript["text"]

📄 FastAPI Endpoint for Upload + Transcript

python
from fastapi import File, UploadFile @app.post("/api/interview/upload-audio") async def upload_audio(file: UploadFile = File(...)): file_path = f"./uploads/{file.filename}" with open(file_path, "wb") as f: f.write(await file.read()) text = transcribe_audio(file_path) db.questions.insert_one({"text": text, "source": file.filename}) return {"question": text}

4. 🧑‍🏫 INTERACTIVE WHITEBOARD

💡 Options:

  • Embed Excalidraw (open-source drawing tool)

  • Embed Ziteboard (with a session URL per interview)

📄 Embed Excalidraw in React

jsx
import { Excalidraw } from "@excalidraw/excalidraw"; const Whiteboard = () => { return ( <div className="h-[600px] border shadow"> <Excalidraw /> </div> ); }; export default Whiteboard;

📊 COMBINED DASHBOARD FLOW (Optional UI Elements)

SectionFeature
Video RoomJitsi/100ms embedded
WhiteboardSide panel with Excalidraw for notes or diagrams
Question CaptureReal-time STT transcript below video window
AssessmentInterviewer panel below with form fields
Chat/DocsFile share, note-taking, transcript download options
=======================================

STAGE 4 — VALUE ADD SERVICES MODULES

Modules Covered:

  1. Résumé Parser

  2. Résumé Rater

  3. Interview Questions Database


1️⃣ RÉSUMÉ PARSER

📌 Purpose: Extract structured data (skills, education, experience) from unstructured résumés.

🔧 Tech Stack:

  • Parser: Python + pdfminer, docx, PyMuPDF

  • NLP: spaCy, re, or transformers for Named Entity Recognition

  • Storage: MongoDB (schemaless)


📄 Key Python Parser Logic

python
import spacy from pdfminer.high_level import extract_text import re nlp = spacy.load("en_core_web_sm") def extract_resume_data(pdf_path): text = extract_text(pdf_path) doc = nlp(text) skills = [] for chunk in doc.noun_chunks: token = chunk.text.lower().strip() if token in SKILL_SET: skills.append(token) email = re.findall(r"\b[\w.-]+?@\w+?\.\w+?\b", text) phone = re.findall(r'\+?\d[\d -]{8,}\d', text) return { "text": text, "skills": list(set(skills)), "email": email[0] if email else "", "phone": phone[0] if phone else "" }

📄 FastAPI Upload Endpoint

python
@app.post("/api/resume/upload") async def upload_resume(file: UploadFile = File(...)): path = f"./uploads/{file.filename}" with open(path, "wb") as f: f.write(await file.read()) parsed = extract_resume_data(path) db.parsed_resumes.insert_one(parsed) return {"status": "Parsed", "skills": parsed["skills"]}

2️⃣ RÉSUMÉ RATER

📌 Purpose: Give a percentage score showing how well a résumé matches a job posting.

💡 Logic:

  • Extract skills from both résumé and JD

  • Compute overlap %

  • Use Sentence Embeddings for smarter matching


📄 Basic Scoring Engine

python
def compute_resume_score(job_description, resume_skills): jd_doc = nlp(job_description) jd_keywords = set([token.text.lower() for token in jd_doc if token.pos_ in ['NOUN', 'PROPN']]) resume_keywords = set(resume_skills) intersection = jd_keywords & resume_keywords if not jd_keywords: return 0 return round(len(intersection) / len(jd_keywords) * 100, 2)

📄 FastAPI Endpoint

python
@app.post("/api/resume/score") def rate_resume(candidate_id: str, job_id: str): resume = db.parsed_resumes.find_one({"candidate_id": candidate_id}) job = db.jobs.find_one({"job_id": job_id}) if not resume or not job: raise HTTPException(status_code=404) score = compute_resume_score(job["description"], resume["skills"]) return {"score": score, "match_level": "High" if score > 70 else "Medium" if score > 40 else "Low"}

3️⃣ INTERVIEW QUESTIONS DATABASE

📌 Purpose: A searchable repository of:

  • Past questions (from STT in live interviews)

  • Crowdsourced Q&A from recruiters/candidates

🔧 Stack:

  • MongoDB for storage

  • Full-text search using MongoDB Atlas Search or Elasticsearch

  • Optional: Tag-based filtering and contributor attribution


📄 MongoDB Schema

json
{ "question": "Explain polymorphism in OOP.", "answer": "Polymorphism is the ability...", "tags": ["OOP", "Java", "Inheritance"], "source": "STT / manual", "contributor_name": "Hemen Parekh", "email": "hemen@example.com" }

📄 FastAPI Endpoints

python
class QAEntry(BaseModel): question: str answer: str tags: list[str] contributor_name: Optional[str] = None email: Optional[str] = None @app.post("/api/interview/qa/add") def add_question(entry: QAEntry): db.qadb.insert_one(entry.dict()) return {"status": "Question added"} @app.get("/api/interview/qa/search") def search_questions(tag: str): results = list(db.qadb.find({"tags": tag})) return results

🧠 FUTURE ADD-ONS (For All Value Services)

FeatureTools / APIs
AI-based Q&A ratingLLM (GPT or Claude) scoring the quality of answer
Resume visualizationRadar graph or spider chart of candidate vs job fit
Candidate insights dashboardBehavioral + skills + historical interview record
Export to PDF or ExcelResume reports with match scores + keyword highlights
======================================================

# 📁 OnlineJobsFair
A modular, AI-enhanced recruitment platform designed for real-time video interviews, smart resume parsing, automated job matching, and employer-candidate collaboration.

---

## 🧱 Project Structure

```
OnlineJobsFair/
├── backend/
│   ├── main.py
│   ├── config.py
│   ├── models/
│   │   ├── employer.py
│   │   ├── candidate.py
│   │   ├── job.py
│   │   └── assessment.py
│   ├── routes/
│   │   ├── auth.py
│   │   ├── employers.py
│   │   ├── candidates.py
│   │   ├── jobs.py
│   │   ├── interview.py
│   │   ├── parser.py
│   │   ├── rater.py
│   │   └── qa.py
│   ├── services/
│   │   ├── resume_parser.py
│   │   ├── match_engine.py
│   │   ├── whisper_stt.py
│   │   └── assessment_scoring.py
│   └── database/
│       └── mongodb.py
├── frontend/
│   ├── public/
│   ├── src/
│   │   ├── App.jsx
│   │   ├── index.jsx
│   │   ├── components/
│   │   │   ├── EmployerDashboard.jsx
│   │   │   ├── CandidateDashboard.jsx
│   │   │   ├── VideoRoom.jsx
│   │   │   ├── Whiteboard.jsx
│   │   │   └── AssessmentForm.jsx
│   │   └── pages/
│   │       ├── Register.jsx
│   │       ├── Login.jsx
│   │       ├── JobSearch.jsx
│   │       └── InterviewRoom.jsx
├── uploads/
├── README.md
├── requirements.txt
├── .env
└── LICENSE
```

---

## 📖 README.md

### 🔹 OnlineJobsFair: Smart Hiring Platform

A complete virtual recruitment system integrating AI-driven resume parsing, video interviews, assessment workflows, and real-time job matching for both employers and candidates.

---

### 🛠️ Features by Module

#### EMPLOYER ZONE
- Business Registration with unique Employer ID
- Job Posting & Candidate Match Index
- Resume Search & Grabber (shared resume pool)
- Payment Account Setup (Razorpay/Stripe)

#### JOBSEEKER ZONE
- 1-step/5-step Registration (with LinkedIn autofill)
- Smart Job Search with AI-based matching
- Auto Notifications for outdated resumes

#### ONLINE JOB FAIR
- Live Video Interviews (Jitsi or 100ms)
- Multi-panel Assessment Form with rating aggregation
- STT transcription of interview questions (Whisper/Vosk)
- Whiteboard collaboration tool (Excalidraw)

#### VALUE ADD SERVICES
- Resume Parser (NLP-based skill extraction)
- Resume Rater (Match Score between JD and Resume)
- Interview QnA Database (with contributor support)

---

### 🧰 Tech Stack
- **Frontend**: React + Tailwind CSS
- **Backend**: FastAPI (Python)
- **Database**: MongoDB
- **NLP/AI**: spaCy, Sentence-BERT, Whisper
- **Search**: SOLR / Elasticsearch (optional)
- **Video SDK**: Jitsi, 100ms, or Agora
- **Auth**: Firebase Auth or Auth0

---

### 🚀 Local Setup

```bash
# Backend Setup
cd backend
pip install -r requirements.txt
uvicorn main:app --reload

# Frontend Setup
cd frontend
npm install
npm run dev
```

---

### 📎 API Highlights
| Endpoint                        | Description                          |
|-------------------------------|--------------------------------------|
| POST /employer/register       | Register a business                  |
| POST /job/post                | Post a new job                       |
| GET /jobs/search              | Search jobs by profile               |
| POST /resume/upload           | Upload & parse a resume              |
| POST /resume/score            | Match resume to job                  |
| POST /assessment/submit       | Submit interviewer rating            |
| POST /interview/upload-audio  | Upload interview audio for STT      |
| POST /interview/qa/add        | Add interview question/answer pair   |

---

### ✅ License
[MIT License](LICENSE)

---

Let me know if you'd like a ZIP or GitHub export, or a visual architecture diagram next.
============================================



Re-imagining teacher education

 



re-imagining teacher education

Extract from the article:
The article from The Hindu Business Line, while primarily focused on re-imagining teacher education, indirectly sheds light on the more profound and often overlooked dynamics that shape political nominations and policymaking in India. It emphasizes the urgent need for systemic reforms in education but also highlights the inertia and entrenched interests that stall progressive change. This inertia is not just a characteristic of educational institutions but resonates broadly in political nomination processes where vested interests, lack of transparency, and traditionalism impede the emergence of fresh, visionary leaders.

Intriguingly, the article advocates for a fresh paradigm—encouraging dialogue between policymakers, educators, and the public to co-create solutions that are sustainable and equitably beneficial. Such inclusive, participatory frameworks contrast starkly with the opaque mechanisms traditionally dominating political nominations, which are often influenced more by internal party hierarchies than the true aspirations of the populace. The underlying message calls for democratizing decision-making at every level, underlining the political nomination dynamics as a microcosm of broader governance challenges.

My Take:

A. #FakeNews ? An Obsolete Concept ?
"Last few days , media ( online + offline ) is full of debate surrounding some govt circular on fake news and its subsequent withdrawal. Todays Economic Times carries following news : I&B Ministry looks at regulating Online News ... The set of regulations has to come out first, after which the code of conduct for online news portals can be worked out."

Looking back at what I wrote several years ago about regulation of news media, particularly online platforms, I realize how prescient those observations were in the context of political nomination dynamics today. The nexus between media narratives and political fortunes has become ever more entwined, with “fake news,” misinformation, and partisan reporting molding public opinion in ways that directly affect who gets nominated and who doesn’t. The lack of a robust regulatory framework in digital news ecosystems makes political nomination battles less about merit and more about influence, spotlight time, and perception engineering. Today, as the call for more transparent and accountable nomination processes grows louder, it becomes evident that media regulation and political democratization share an intricate, mutual dependency.

The challenge I highlighted about crafting suitable regulation without stifling freedom also mirrors the balancing act needed in political reforms. If nominations are to embody genuine democratic choices rather than hierarchical impositions, the transparency and fairness in communication channels, including regulated and unbiased media, become indispensable. The political sphere cannot remain insulated while the media’s power to shape narratives goes unchecked. This interplay is a crucial consideration for anyone seeking to understand or influence nomination dynamics in contemporary India.

B. Peoples Pulse ? Peoples Confusion ?
"PM Modi uses app to pick poll nominees, making netas worry … the survey is quite wide ranging , and without any focus! ...Why did I feel this way? To get a feel, take a look at the format..."

Reflecting on my earlier blog that covered the "Peoples Pulse" app initiative by PM Modi to democratize political engagement, I had then sensed both promise and pitfalls. The idea of digitizing public opinion for nomination decisions was revolutionary—implying a break from closed-door deals to wider citizen participation. However, my critique on the app’s lack of focus and overly broad questioning remains relevant today. While digital tools have proliferated, the core challenge persists: How do you ensure that the selection process is not just participative in form but deep and discerning in content?

In the realm of political nominations, there is often a gap between tokenistic public consultation and meaningful public mandate. The “wide ranging” but “unfocused” nature of surveys mirrors the broader democratic quandary of capturing nuanced voter preferences rather than simplistic popularity contests. If nominations are to truly represent the electorate’s pulse, the mechanisms must be refined to harness clarity, priority, and actionable insight rather than volume and vagueness. My past reflections signal the road ahead—technology can be an enabler but not a panacea for democratic deficits in political nominations.

Call to Action:
To the political parties and election commission authorities: It is time to transcend entrenched nomination norms steeped in favoritism, opacity, and inertia. Adopt transparent, data-driven, and participatory approaches that integrate technology wisely—amplifying genuine public voice without reducing the process to a popularity contest. Embrace regulatory frameworks that address media’s role in shaping nomination narratives, ensuring fair and factual dissemination. Most importantly, engage educators, civil society, and citizen platforms to collaboratively reimagine nomination dynamics, forging a more inclusive democratic fabric that reflects the true aspirations of the people.

With regards, 

Hemen Parekh

www.My-Teacher.in