from fastapi import FastAPI from pydantic import BaseModel from google.oauth2.service_account import Credentials import gspread from google.auth.exceptions import GoogleAuthError import os import uvicorn app = FastAPI() # Define chapter categories physics_chapters = { "physics and measurement", "kinematics", "laws of motion", "work, energy, and power", "rotational motion", "gravitation", "properties of solids and liquids", "thermodynamics", "kinetic theory of gases", "oscillations and waves", "electrostatics", "current electricity", "magnetic effects of current and magnetism", "electromagnetic induction and alternating currents", "electromagnetic waves", "optics", "dual nature of matter and radiation", "atoms and nuclei", "electronic devices" } chemistry_chapters = { "some basic concepts in chemistry", "atomic structure", "chemical bonding and molecular structure", "chemical thermodynamics", "solutions", "equilibrium", "redox reactions and electrochemistry", "chemical kinetics", "classifications of elements and periodicity in properties", "p- block elements", "d - and f - block elements", "co-ordination compounds", "purification and characterisation of organic compounds", "some basic principles of organic chemistry", "hydrocarbons", "organic compounds containing halogens", "organic compounds containing oxygen", "organic compounds containing nitrogen", "biomolecules" } maths_chapters = { "sets, relation and functions", "complex numbers and quadratic equations", "matrices and determinants", "permutations and combinations", "binomial theorem", "sequence and series", "limits, continuity, and diffrentiability", "integral calculus", "diffrential equations", "co-ordinate geometry", "straight lines", "circle and conic sections", "three dimensional geometry", "vector algebra", "statistics and probability", "trigonometry" } # class Chapter: # def __init__(self): # self.data = {} # def add_marks(self, chapter_name, marks): # if chapter_name not in self.data: # self.data[chapter_name] = {"sum_marks": 0, "count": 0} # self.data[chapter_name]["sum_marks"] += marks # self.data[chapter_name]["count"] += 1 # def print_averages(self): # for chapter, stats in self.data.items(): # if stats["count"] > 0: # avg = stats["sum_marks"] / stats["count"] # return f"{chapter}: Average = {round(avg, 1)}" class Chapter: def __init__(self): self.data = {} def add_marks(self, chapter_name, marks): if chapter_name not in self.data: self.data[chapter_name] = {"sum_marks": 0, "count": 0} self.data[chapter_name]["sum_marks"] += marks self.data[chapter_name]["count"] += 1 def print_averages(self): averages = {} for chapter, stats in self.data.items(): if stats["count"] > 0: avg = stats["sum_marks"] / stats["count"] averages[chapter] = round(avg, 1) else: averages[chapter] = 0 return averages class PhysicsChapter(Chapter): pass class ChemistryChapter(Chapter): pass class MathsChapter(Chapter): pass def get_credentials_from_env(): service_account_info = { "type": os.getenv("SERVICE_ACCOUNT_TYPE"), "project_id": os.getenv("PROJECT_ID"), "private_key_id": os.getenv("PRIVATE_KEY_ID"), "private_key": os.getenv("PRIVATE_KEY").replace('\\n', '\n'), "client_email": os.getenv("CLIENT_EMAIL"), "client_id": os.getenv("CLIENT_ID"), "auth_uri": os.getenv("AUTH_URI"), "token_uri": os.getenv("TOKEN_URI"), "auth_provider_x509_cert_url": os.getenv("AUTH_PROVIDER_X509_CERT_URL"), "client_x509_cert_url": os.getenv("CLIENT_X509_CERT_URL"), "universe_domain": os.getenv("UNIVERSE_DOMAIN") } scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive'] creds = Credentials.from_service_account_info(service_account_info, scopes=scope) return creds @app.get("/analyze_chapter_averages") def analyze_chapter_averages(): try: # Set up credentials creds = get_credentials_from_env() client = gspread.authorize(creds) # Open the Google Sheet (replace with your sheet URL) sheet = client.open_by_url('https://docs.google.com/spreadsheets/d/13PUHySUXWtKBusjugoe7Dbsm39PwBUfG4tGLipspIx4/edit?gid=0#gid=0').worksheet('Sheet1') # Get all values from the sheet data = sheet.get_all_values() # Initialize objects for each subject physics_tracker = PhysicsChapter() chemistry_tracker = ChemistryChapter() maths_tracker = MathsChapter() # Iterate over each row in the data for row in data[1:]: # Assuming the first row is headers user_id = row[0] # First column is user_id i = 1 while i < len(row): chapter_name = row[i] # Ensure chapter_name is a string and marks are valid numbers if isinstance(chapter_name, str): chapter_name = chapter_name.strip().lower() marks = row[i + 1] if isinstance(marks, (int, float)): # Check if the chapter belongs to Physics, Chemistry, or Maths if chapter_name in physics_chapters: physics_tracker.add_marks(chapter_name, marks) elif chapter_name in chemistry_chapters: chemistry_tracker.add_marks(chapter_name, marks) elif chapter_name in maths_chapters: maths_tracker.add_marks(chapter_name, marks) i += 2 # Move to the next chapter and marks # Return average marks per chapter for each subject return { "Physics Chapters": physics_tracker.print_averages(), "Chemistry Chapters": chemistry_tracker.print_averages(), "Maths Chapters": maths_tracker.print_averages() } except GoogleAuthError as e: return {"error": f"Authentication error: {e}"} except gspread.exceptions.SpreadsheetNotFound: return {"error": "Spreadsheet not found. Please check the URL."} except Exception as e: return {"error": f"An error occurred: {e}"} if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)