1. UTF-8 Bugfix: Fixed byte-casting in views::rich() that turned multi-byte UTF-8 sequences into Latin-1 mojibake (e.g. 2.06 × 10 -> 2.06 × 10). 2. Question Typography: Replaced nested <p class='stem'> with <div class='stem'> and strict CSS overrides ensuring consistent 1.0625rem font-size and weight across all 9,837 questions regardless of inner tags. 3. Modern Educational Theme: Removed harsh minimal 0-radius monospace styling; introduced comfortable slate dark theme (#090d16), rounded corners (8-12px), Inter typography, and refined option card states. 4. Topic Selection (/build) Revamp: - Added Quick Presets bar (Full Mock 75 Qs, Physics/Chemistry/Maths focus, Clear). - Added Subject Navigation Tabs (All, Physics, Chemistry, Mathematics). - Independent subtopic expand chevrons that don't force-check parent chapters. - Live question pool estimator and interactive count pills. 5. JEE Portion Reorganization (scripts/reorganize_jee_db.py): Re-categorized the database into the 15 official JEE Main units across Physics, Chemistry, and Mathematics.
203 lines
7.7 KiB
Python
203 lines
7.7 KiB
Python
#!/usr/bin/env python3
|
||
"""Reorganizes and cleanses whaleprep.db to match official JEE Main portions.
|
||
|
||
1. Fixes mojibake / corrupted UTF-8 sequences in all questions.
|
||
2. Reorganizes chapters into the 15 standard JEE Main syllabus units:
|
||
Physics (6):
|
||
- Mechanics
|
||
- Thermal Physics & Thermodynamics
|
||
- Oscillations & Waves
|
||
- Electricity & Magnetism
|
||
- Optics
|
||
- Modern Physics & Electronics
|
||
Chemistry (3):
|
||
- Physical Chemistry
|
||
- Inorganic Chemistry
|
||
- Organic Chemistry
|
||
Maths (6):
|
||
- Algebra
|
||
- Calculus
|
||
- Coordinate Geometry
|
||
- Vectors & 3D Geometry
|
||
- Trigonometry
|
||
- Probability & Statistics
|
||
3. Re-assigns subtopics and questions to their respective official chapter.
|
||
4. Cleans up empty / duplicate chapters.
|
||
"""
|
||
|
||
import sqlite3
|
||
import sys
|
||
|
||
def get_or_create_chapter(cur, subject, name):
|
||
row = cur.execute("SELECT id FROM chapters WHERE subject=? AND name=?", (subject, name)).fetchone()
|
||
if row:
|
||
return row[0]
|
||
cur.execute("INSERT INTO chapters(subject, name) VALUES(?, ?)", (subject, name))
|
||
return cur.lastrowid
|
||
|
||
def main(db_path):
|
||
con = sqlite3.connect(db_path)
|
||
cur = con.cursor()
|
||
|
||
print(f"Opening database: {db_path}")
|
||
|
||
# 1. MOJIBAKE CLEANSE in questions
|
||
print("--- 1. Cleansing Mojibake ---")
|
||
replacements = [
|
||
("×", "×"),
|
||
("°", "°"),
|
||
("±", "±"),
|
||
("µ", "µ"),
|
||
("–", "–"),
|
||
("—", "—"),
|
||
("’", "’"),
|
||
("‘", "‘"),
|
||
("“", "“"),
|
||
("â€", "”"),
|
||
("≈", "≈"),
|
||
("≤", "≤"),
|
||
("≥", "≥"),
|
||
("Â", ""), # stray non-breaking space artifact
|
||
]
|
||
|
||
rows = cur.execute("SELECT id, stem, opt_a, opt_b, opt_c, opt_d, solution FROM questions").fetchall()
|
||
fixed_count = 0
|
||
for qid, stem, a, b, c, d, sol in rows:
|
||
orig = (stem, a, b, c, d, sol)
|
||
new = []
|
||
for text in orig:
|
||
if not text:
|
||
new.append(text)
|
||
continue
|
||
t = text
|
||
for bad, good in replacements:
|
||
if bad in t:
|
||
t = t.replace(bad, good)
|
||
new.append(t)
|
||
if tuple(new) != orig:
|
||
cur.execute(
|
||
"UPDATE questions SET stem=?, opt_a=?, opt_b=?, opt_c=?, opt_d=?, solution=? WHERE id=?",
|
||
(*new, qid)
|
||
)
|
||
fixed_count += 1
|
||
print(f"Fixed mojibake in {fixed_count} questions.")
|
||
|
||
# 2. CHAPTER REORGANIZATION
|
||
print("--- 2. Reorganizing JEE Syllabus Portions ---")
|
||
|
||
# Rename existing chapters for clarity
|
||
cur.execute("UPDATE chapters SET name='Electricity & Magnetism' WHERE subject='Physics' AND name='Electricity'")
|
||
cur.execute("UPDATE chapters SET name='Modern Physics & Electronics' WHERE subject='Physics' AND name='Modern Physics'")
|
||
|
||
# Target chapters
|
||
p_thermal = get_or_create_chapter(cur, "Physics", "Thermal Physics & Thermodynamics")
|
||
p_waves = get_or_create_chapter(cur, "Physics", "Oscillations & Waves")
|
||
p_elec = get_or_create_chapter(cur, "Physics", "Electricity & Magnetism")
|
||
p_optics = get_or_create_chapter(cur, "Physics", "Optics")
|
||
|
||
m_vec = get_or_create_chapter(cur, "Maths", "Vectors & 3D Geometry")
|
||
m_prob = get_or_create_chapter(cur, "Maths", "Probability & Statistics")
|
||
m_coord = get_or_create_chapter(cur, "Maths", "Coordinate Geometry")
|
||
m_trig = get_or_create_chapter(cur, "Maths", "Trigonometry")
|
||
|
||
# A. Move Thermal Physics subtopics out of Mechanics
|
||
thermal_subs = [
|
||
'Heat Engine Second Law Of Thermodynamics And Carnot Engine',
|
||
'Heat Transfer',
|
||
'Specific Heat Capacity Calorimetry And Change Of State',
|
||
'Kinetic Theory Of Gases And Gas Laws',
|
||
'Thermodynamics Process',
|
||
'Zeroth And First Law Of Thermodynamics',
|
||
'Thermometry And Thermal Expansion'
|
||
]
|
||
for s in thermal_subs:
|
||
cur.execute("UPDATE subtopics SET chapter_id=? WHERE name=?", (p_thermal, s))
|
||
|
||
# B. Move Oscillations & Waves subtopics out of Mechanics
|
||
wave_subs = [
|
||
'Simple Harmonic Motion',
|
||
'Some Systems Of Executing Shm',
|
||
'Forced Damped Oscillations And Resonance',
|
||
'Superposition And Reflection Of Waves',
|
||
'Basic Of Waves And Progressive Waves',
|
||
'Doppler Effect'
|
||
]
|
||
for s in wave_subs:
|
||
cur.execute("UPDATE subtopics SET chapter_id=? WHERE name=?", (p_waves, s))
|
||
|
||
# C. Merge Physics Electromagnetism (seed) into Electricity & Magnetism
|
||
old_em = cur.execute("SELECT id FROM chapters WHERE subject='Physics' AND name='Electromagnetism'").fetchone()
|
||
if old_em:
|
||
cur.execute("UPDATE subtopics SET chapter_id=? WHERE chapter_id=?", (p_elec, old_em[0]))
|
||
cur.execute("DELETE FROM chapters WHERE id=?", (old_em[0],))
|
||
|
||
# D. Move Vectors & 3D subtopics out of Algebra
|
||
vec_subs = [
|
||
'Lines And Plane',
|
||
'Plane In Space',
|
||
'Direction Cosines And Direction Ratios Of A Line',
|
||
'Lines In Space',
|
||
'Vectors',
|
||
'3D Geometry'
|
||
]
|
||
for s in vec_subs:
|
||
cur.execute("UPDATE subtopics SET chapter_id=? WHERE name=?", (m_vec, s))
|
||
|
||
# E. Move Probability & Statistics subtopics out of Algebra
|
||
prob_subs = [
|
||
'Classical Defininition Of Probability',
|
||
'Probability Distribution Of A Random Variable',
|
||
'Conditional Probability And Multiplication Theorem',
|
||
'Total Probability Theorem',
|
||
'Calculation Of Standard Deviation Variance And Mean Deviation Of Grouped And Ungrouped Data',
|
||
'Probability'
|
||
]
|
||
for s in prob_subs:
|
||
cur.execute("UPDATE subtopics SET chapter_id=? WHERE name=?", (m_prob, s))
|
||
|
||
# F. Merge Maths Geometry (seed) into Coordinate Geometry
|
||
old_geom = cur.execute("SELECT id FROM chapters WHERE subject='Maths' AND name='Geometry'").fetchone()
|
||
if old_geom:
|
||
cur.execute("UPDATE subtopics SET chapter_id=? WHERE chapter_id=?", (m_coord, old_geom[0]))
|
||
cur.execute("DELETE FROM chapters WHERE id=?", (old_geom[0],))
|
||
|
||
# G. Delete duplicate empty Trigonometry chapters
|
||
trig_rows = cur.execute("SELECT id FROM chapters WHERE subject='Maths' AND name='Trigonometry'").fetchall()
|
||
for row in trig_rows:
|
||
cnt = cur.execute("SELECT count(*) FROM subtopics WHERE chapter_id=?", (row[0],)).fetchone()[0]
|
||
qcnt = cur.execute("SELECT count(*) FROM questions q JOIN subtopics s ON s.id=q.subtopic_id WHERE s.chapter_id=?", (row[0],)).fetchone()[0]
|
||
if qcnt == 0:
|
||
cur.execute("DELETE FROM subtopics WHERE chapter_id=?", (row[0],))
|
||
cur.execute("DELETE FROM chapters WHERE id=?", (row[0],))
|
||
|
||
# 3. Synchronize question.chapter_id with subtopic.chapter_id
|
||
print("--- 3. Synchronizing Question Chapter IDs ---")
|
||
cur.execute("""
|
||
UPDATE questions
|
||
SET chapter_id = (SELECT chapter_id FROM subtopics WHERE subtopics.id = questions.subtopic_id)
|
||
WHERE subtopic_id IN (SELECT id FROM subtopics)
|
||
""")
|
||
|
||
con.commit()
|
||
|
||
print("\n=== FINAL JEE MAIN CHAPTER STRUCTURE ===")
|
||
results = cur.execute("""
|
||
SELECT c.subject, c.name,
|
||
count(DISTINCT s.id) as sub_cnt,
|
||
count(q.id) as q_cnt
|
||
FROM chapters c
|
||
LEFT JOIN subtopics s ON s.chapter_id = c.id
|
||
LEFT JOIN questions q ON q.chapter_id = c.id
|
||
GROUP BY c.subject, c.name
|
||
ORDER BY c.subject, c.name
|
||
""").fetchall()
|
||
|
||
for subj, cname, sub_cnt, q_cnt in results:
|
||
print(f" {subj:<12} | {cname:<35} | {sub_cnt:>2} subtopics | {q_cnt:>5} questions")
|
||
|
||
con.close()
|
||
print("\nDatabase reorganization complete!")
|
||
|
||
if __name__ == "__main__":
|
||
db = sys.argv[1] if len(sys.argv) > 1 else "whaleprep.db"
|
||
main(db)
|