University-grade result processing platform β built for SPPU affiliated colleges
Parse Β· Validate Β· Analyse Β· Export β all in one platform.
| Feature | Description |
|---|---|
| π Automated PDF Parsing | Extracts structured student data from text-based university ledger PDFs using pdfplumber |
| π Dynamic Metadata Detection | Auto-detects university, college, department, session, and semester β zero hardcoding |
| 𧬠Dynamic Subject Detection | Subject codes detected at runtime β works for any department, any semester |
| π« Duplicate Protection | Prevents re-upload of the same semester using a composite key check |
| β Pre-save Validation | Validates SGPA consistency, PRN format, and subject counts before saving |
| π Analytics Dashboard | Pass/fail stats, SGPA distribution, subject-wise analytics, ranked student lists, and subject difficulty scoring |
| π₯ Selective Excel Export | Choose which sheets to include β Summary, Rank List, Subject Analytics, SGPA Distribution |
| π History Management | View, audit, and admin-delete previously uploaded semesters |
| π₯ Firebase Backend | Google Firebase Firestore β reliable, fast, reachable from any network |
| π¨ Dark / Light Theme | Toggle between dark navy and clean white theme with a single click |
| π 3-Tier Authentication | Separate READ, WRITE, and ADMIN passwords with admin-only features |
| π Semester Comparison | Compare multiple semesters side-by-side with trend analysis |
| π Subject Difficulty | Weighted difficulty scoring: (Fail% Γ 0.6) + ((100 β AvgMarks) Γ 0.4) |
ResultOps/
βββ app.py # Streamlit entry point β routing, theme, auth, sidebar
βββ logo.png # App logo (sidebar + README)
βββ setup.cfg # Tool configuration (flake8, mypy, pytest)
βββ requirements.txt # Production dependencies
βββ requirements-dev.txt # Dev dependencies (testing, linting, security)
βββ .env.example # Environment variable template
β
βββ parser/ # PDF extraction & parsing pipeline
β βββ __init__.py
β βββ pdf_parser.py # Raw text extraction via pdfplumber
β βββ metadata_extractor.py # University, college, department, session detection
β βββ student_parser.py # Student block splitting + subject line parsing
β βββ refactored_parser.py # Unified pipeline β orchestrates metadata + students + confidence
β
βββ database/
β βββ __init__.py
β βββ db.py # Firebase Admin SDK client (Streamlit secrets + .env fallback)
β
βββ analytics/
β βββ __init__.py
β βββ analytics.py # Queries, ranking, comparison, difficulty, SGPA distribution
β
βββ services/
β βββ __init__.py
β βββ result_service.py # Firestore writes, batch inserts, duplicate guard
β βββ excel_export.py # Styled multi-sheet Excel workbook generator
β
βββ views/ # Streamlit page views
β βββ __init__.py
β βββ upload_page.py # PDF upload, parse preview, validation, save, inline Excel export
β βββ analytics_page.py # Dashboard β charts, tables, view toggle, selective Excel download
β βββ history_page.py # Upload history + admin-only delete
β βββ system_stats.py # System statistics (admin-only)
β
βββ utils/
β βββ __init__.py
β βββ theme.py # Dark/light theme manager with full CSS injection
β βββ auth.py # 3-tier authentication (READ / WRITE / ADMIN)
β βββ validators.py # Pre-save data validation (SGPA, PRN, subjects)
β
βββ test/
β βββ __init__.py
β βββ test_parser.py # Unit + integration tests for parser and ranking
β βββ test_connection.py # Firebase connectivity check script
β
βββ .github/workflows/
β βββ ci.yml # GitHub Actions CI β black, flake8, mypy, pytest, bandit
β
βββ .streamlit/
β βββ config.toml # Streamlit server configuration
β
βββ docs/
β βββ hosting.md # Step-by-step Streamlit Cloud deployment guide
β βββ github_actions.md # GitHub Actions CI/CD setup guide
β
βββ hash_password/ # Utility to generate SHA-256 password hashes
flowchart TD
classDef user fill:#1a4a8a,stroke:#2d8cff,stroke-width:2px,color:#e8f0fe
classDef parser fill:#7c4a00,stroke:#f5a623,stroke-width:2px,color:#fff8ee
classDef validate fill:#7a0022,stroke:#ff4d6d,stroke-width:2px,color:#ffe8ec
classDef firebase fill:#004d2e,stroke:#00d97e,stroke-width:2px,color:#e0fff4
classDef analytics fill:#3b1f7a,stroke:#a78bfa,stroke-width:2px,color:#f0ebff
classDef export fill:#004a4a,stroke:#06d6c7,stroke-width:2px,color:#e0fffe
classDef decision fill:#1a3a1a,stroke:#00d97e,stroke-width:2px,color:#e0fff4
subgraph USER["π€ USER LAYER"]
direction LR
A["π€ Faculty / Admin"]
B["π₯οΈ Streamlit Web App<br/>app.py Β· Port 8501"]
end
subgraph PAGES["π PAGE VIEWS"]
direction LR
P1["π€ Upload Page<br/>upload_page.py"]
P2["π Analytics Page<br/>analytics_page.py"]
P3["π History Page<br/>history_page.py"]
P4["βοΈ System Stats<br/>system_stats.py"]
end
subgraph PARSE["π PDF PROCESSING LAYER"]
direction LR
C["π PDF Parser<br/>pdf_parser.py<br/>pdfplumber text extraction"]
D["π Metadata Extractor<br/>metadata_extractor.py<br/>University Β· College Β· Dept Β· Sem"]
E["π₯ Student Parser<br/>student_parser.py<br/>PRN Β· SGPA Β· Subjects"]
F["π Unified Pipeline<br/>refactored_parser.py<br/>Orchestrator + Confidence Score"]
end
subgraph AUTH["π AUTH + VALIDATION"]
direction LR
G["π 3-Tier Auth<br/>auth.py<br/>READ Β· WRITE Β· ADMIN"]
H["π§ͺ Data Validator<br/>validators.py"]
I{"π« Duplicate Guard<br/>Semester Key Check"}
end
subgraph FIRE["π₯ FIREBASE FIRESTORE"]
direction LR
J["π₯ Firebase SDK<br/>db.py"]
K["π semesters<br/>collection"]
L["π results<br/>collection"]
end
subgraph OUT["π ANALYTICS + EXPORT"]
direction LR
M["π Analytics Engine<br/>analytics.py<br/>Ranking Β· Comparison Β· Difficulty"]
N["π₯ Excel Export<br/>excel_export.py<br/>Selective Β· Styled Β· Multi-sheet"]
O["β¬οΈ Browser Download<br/>.xlsx"]
end
A -->|"Login"| G
G -->|"Authenticated"| B
B --> P1 & P2 & P3 & P4
P1 -->|"Upload PDF"| C
C -->|"Raw text"| F
F --> D & E
D -->|"PDFMetadata"| F
E -->|"StudentRecord list"| F
F -->|"Parsed data"| H
H -->|"Validated"| I
I -->|"β Exists"| P1
I -->|"β
New"| J
J -->|"batch write"| K
J -->|"batch write Γ N"| L
P2 -->|"Query"| M
L -->|"docs"| M
K -.-|"metadata"| M
M -->|"DataFrames"| P2
M --> N
N --> O
P3 -->|"List/Delete"| J
P4 -->|"Stats"| J
class A,B user
class P1,P2,P3,P4 user
class C,D,E,F parser
class G,H validate
class I decision
class J,K,L firebase
class M analytics
class N,O export
Upload Data Flow:
PDF Upload β Text Extract β Metadata Detect β Student Parse β Confidence Score
β Validate β Duplicate Check β Firestore Write β Excel Export
Firestore Collections:
| Collection | Doc ID | Contents |
|---|---|---|
semesters |
University|College|Dept|Sem|Session|Year |
Metadata + student count |
results |
Auto-generated | PRN, SGPA, Status, subjects[] nested array |
ResultOps uses 3-tier password authentication, all hashed with SHA-256:
| Tier | Access Level | Features |
|---|---|---|
| π’ READ | View-only analytics | Dashboard, analytics, history (view only) |
| π‘ WRITE | Upload & save data | Upload PDF, parse, save to database |
| π΄ ADMIN | Full control | System Stats, delete records from History |
-
Generate SHA-256 hashes for your passwords:
python -c "import hashlib; print(hashlib.sha256('your_password'.encode()).hexdigest())" -
Add hashes to
.env:READ_PASSWORD_HASH=<sha256_hash_of_read_password> WRITE_PASSWORD_HASH=<sha256_hash_of_write_password> ADMIN_PASSWORD_HASH=<sha256_hash_of_admin_password>
| Role | Default Password |
|---|---|
| READ | password |
| WRITE | password |
| ADMIN | password |
β οΈ Change these immediately after first setup.
git clone https://github.com/himanshu-jadhav108/ResultOps.git
cd ResultOps
python -m venv venv
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate
pip install -r requirements.txt- Go to console.firebase.google.com
- Add Project β name it
ResultOpsβ disable Analytics β Create Project
- Build β Firestore Database β Create Database
- Choose Start in test mode β Region: asia-south1 (Mumbai) β Enable
- βοΈ gear icon β Project Settings β Service Accounts
- Generate new private key β Generate Key
- Rename to
firebase_key.jsonβ place in project root
β οΈ Never commitfirebase_key.jsonto GitHub. Already in.gitignore.
cp .env.example .envEdit .env with your password hashes:
FIREBASE_KEY_PATH=firebase_key.json
READ_PASSWORD_HASH=<your_read_hash>
WRITE_PASSWORD_HASH=<your_write_hash>
ADMIN_PASSWORD_HASH=<your_admin_hash>streamlit run app.pyResultOps has a built-in dark/light theme toggle:
| Theme | Background | Sidebar | Text |
|---|---|---|---|
| π Dark | Navy #060e1f |
Gradient navyβblue | White #e8f0fe |
| βοΈ Light | Soft grey #f4f7fb |
Same dark gradient | Dark #0f1e3a |
Toggle via the sidebar button β all elements are fully styled for both themes.
| Feature | Description |
|---|---|
| π Semester Overview | 6 key metrics: students, avg SGPA, highest, distinctions, pass count/% |
| π SGPA Distribution | Bar chart + table with percentage breakdown |
| π Student Rankings | Top 10 highlighted list, full rank list in expander, fail list |
| π Subject Analytics | Pass %, average marks, highest/lowest per subject with color-coded table |
| ποΈ View Mode Toggle | Switch between Charts Only / Tables Only / Both β fully reversible |
| β¬οΈ Selective Excel Download | Choose sheets: Summary, Rank List, Subject Analytics, SGPA Distribution |
Requires text-based (not scanned) SPPU ledger PDFs. Structure:
PRN: XXXXX SEAT NO.: YYY NAME: Student Name
SEMESTER: 5
410241 45 18 20 -- 83 4 O 10 40
...
Winter Session 2025 SGPA : 8.50 Credits Earned/Total : 24/24
SGPA: (SEM-5) 8.50
Quick check: Open PDF in Adobe Reader β try to select/copy text. If it works, ResultOps can parse it.
| Variable | Description |
|---|---|
FIREBASE_KEY_PATH |
Path to Firebase service account JSON key |
READ_PASSWORD_HASH |
SHA-256 hash for read-only access |
WRITE_PASSWORD_HASH |
SHA-256 hash for upload/write access |
ADMIN_PASSWORD_HASH |
SHA-256 hash for admin access (stats, delete) |
The GitHub Actions CI pipeline runs on every push to main and develop:
| Step | Tool | What it checks |
|---|---|---|
| Formatting | black --check . |
Code style consistency |
| Lint (strict) | flake8 --select=E9,F63,F7,F82 |
Syntax errors, undefined names |
| Lint (warnings) | flake8 --exit-zero |
Line length, complexity (non-blocking) |
| Type Check | mypy |
Type annotations in parser/, utils/, analytics/ |
| Tests | pytest test/ -v |
12 unit + integration tests |
| Security | bandit -ll |
Common security vulnerabilities |
| Operation | Target |
|---|---|
| Parse 100 students from PDF | < 5 seconds |
| Firestore batch write (100 students) | < 3 seconds |
| Analytics query | < 1 second |
| Error | Fix |
|---|---|
FileNotFoundError: firebase_key.json |
Place key file in project root |
Invalid service account certificate |
Re-download key from Firebase Console |
TransportError / network failure |
Check internet, switch to mobile hotspot |
PermissionDenied |
Set Firestore rules to test mode |
0 students detected |
PDF must be text-based, not scanned |
Semester not detected |
PDF must contain SEMESTER: N pattern |
| Sidebar shows raw HTML | Run pip install --upgrade streamlit |
| Light theme text invisible | Clear browser cache, hard refresh (Ctrl+Shift+R) |
| Document | Description |
|---|---|
| hosting.md | Step-by-step guide to deploy on Streamlit Cloud |
| github_actions.md | GitHub Actions CI/CD pipeline setup |
- Firebase key used server-side only via
firebase-adminSDK firebase_key.jsonin.gitignoreβ never committed to version control- All passwords stored as SHA-256 hashes β no plaintext anywhere
- Admin password gates destructive operations (delete, system stats)
- Firestore in test mode for dev β restrict rules before going to production
Himanshu Jadhav Second-Year Engineering Student β AI & Data Science
Built with β€οΈ for Savitribai Phule Pune University affiliated colleges