diff --git a/Sora b/Sora
new file mode 100644
index 0000000..eb8ed2e
--- /dev/null
+++ b/Sora
@@ -0,0 +1,453 @@
+import React from 'react';
+import { useState, useEffect, useMemo, useCallback } from 'react';
+import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
+import { BookOpen, BrainCircuit, Calculator, CheckCircle, ChevronDown, ChevronUp, Clock, Coffee, Heart, HelpCircle, ListTodo, Play, Pause, RefreshCw, Smile, Target, Zap } from 'lucide-react';
+
+// Helper Functions & Hooks
+const useLocalStorage = (key, initialValue) => {
+ const [storedValue, setStoredValue] = useState(() => {
+ try {
+ const item = window.localStorage.getItem(key);
+ return item ? JSON.parse(item) : initialValue;
+ } catch (error) {
+ console.error(error);
+ return initialValue;
+ }
+ });
+
+ const setValue = (value) => {
+ try {
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
+ setStoredValue(valueToStore);
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
+ } catch (error) {
+ console.error(error);
+ }
+ };
+
+ return [storedValue, setValue];
+};
+
+// Custom Modal for alerts
+const CustomAlert = ({ message, onClose }) => {
+ if (!message) return null;
+
+ return (
+
+ );
+};
+
+
+// Components
+
+const PomodoroTimer = ({ setTotalStudyTime }) => {
+ const [studyDuration, setStudyDuration] = useLocalStorage('pomodoro:studyDuration', 20);
+ const [timeLeft, setTimeLeft] = useLocalStorage('pomodoro:timeLeft', 20 * 60);
+ const [isActive, setIsActive] = useLocalStorage('pomodoro:isActive', false);
+ const [mode, setMode] = useLocalStorage('pomodoro:mode', 'study'); // study, break, longBreak
+ const [round, setRound] = useLocalStorage('pomodoro:round', 1);
+ const [alertMessage, setAlertMessage] = useState('');
+
+
+ const breakDuration = useMemo(() => Math.floor(studyDuration * 0.2 * 60), [studyDuration]);
+ const longBreakDuration = useMemo(() => Math.floor((studyDuration * 4) * 0.2 * 60), [studyDuration]);
+
+ const handleTimerEnd = useCallback(() => {
+ setIsActive(false);
+ setAlertMessage('Time is up! Remember to have a glass of water to stay hydrated.');
+ if (mode === 'study') {
+ if (round < 4) {
+ setMode('break');
+ setTimeLeft(breakDuration);
+ setRound(r => r + 1);
+ } else {
+ setMode('longBreak');
+ setTimeLeft(longBreakDuration);
+ setRound(1);
+ }
+ } else {
+ setMode('study');
+ setTimeLeft(studyDuration * 60);
+ }
+ }, [mode, round, breakDuration, longBreakDuration, studyDuration]);
+
+ useEffect(() => {
+ let interval = null;
+ if (isActive && timeLeft > 0) {
+ interval = setInterval(() => {
+ setTimeLeft(timeLeft - 1);
+ if (mode === 'study') {
+ setTotalStudyTime(prev => prev + 1);
+ }
+ }, 1000);
+ } else if (isActive && timeLeft === 0) {
+ handleTimerEnd();
+ }
+ return () => clearInterval(interval);
+ }, [isActive, timeLeft, mode, setTotalStudyTime, handleTimerEnd]);
+
+ const toggleTimer = () => {
+ setIsActive(!isActive);
+ };
+
+ const resetTimer = () => {
+ setIsActive(false);
+ setMode('study');
+ setRound(1);
+ setTimeLeft(studyDuration * 60);
+ };
+
+ const handleDurationChange = (e) => {
+ const newDuration = parseInt(e.target.value, 10);
+ if (!isNaN(newDuration) && newDuration > 0) {
+ setStudyDuration(newDuration);
+ if (!isActive) {
+ setTimeLeft(newDuration * 60);
+ }
+ }
+ }
+
+ const formatTime = (seconds) => {
+ const minutes = Math.floor(seconds / 60);
+ const secs = seconds % 60;
+ return `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
+ };
+
+ const progress = (mode === 'study' ? (studyDuration * 60 - timeLeft) / (studyDuration * 60) :
+ mode === 'break' ? (breakDuration - timeLeft) / breakDuration :
+ (longBreakDuration - timeLeft) / longBreakDuration) * 100;
+
+ return (
+ <>
+ setAlertMessage('')} />
+
+
Pomodoro Timer
+
+
+
+
+
{formatTime(timeLeft)}
+
{mode} - Round {round}
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+const SpacedRepetition = () => {
+ const [topics, setTopics] = useLocalStorage('srs:topics', []);
+ const [newTopic, setNewTopic] = useState('');
+ const today = useMemo(() => new Date().setHours(0, 0, 0, 0), []);
+
+ const scheduleReviews = (startDate) => {
+ const intervals = [1, 3, 5, 7, 14, 21, 28, 30];
+ const start = new Date(startDate);
+ return intervals.map(day => {
+ const reviewDate = new Date(start);
+ reviewDate.setDate(start.getDate() + day);
+ return { date: reviewDate.toISOString().split('T')[0], completed: false };
+ });
+ };
+
+ const addTopic = () => {
+ if (newTopic.trim() === '') return;
+ const startDate = new Date().toISOString().split('T')[0];
+ setTopics([...topics, {
+ id: Date.now(),
+ name: newTopic,
+ startDate,
+ reviews: scheduleReviews(startDate)
+ }]);
+ setNewTopic('');
+ };
+
+ const toggleCompletion = (topicId, reviewDateStr) => {
+ setTopics(topics.map(topic => {
+ if (topic.id === topicId) {
+ const updatedReviews = topic.reviews.map(review => {
+ if (review.date === reviewDateStr) {
+ return { ...review, completed: !review.completed };
+ }
+ return review;
+ });
+ return { ...topic, reviews: updatedReviews };
+ }
+ return topic;
+ }));
+ };
+
+ const upcomingRevisions = useMemo(() => {
+ return topics.flatMap(topic =>
+ topic.reviews
+ .filter(r => !r.completed && new Date(r.date).setHours(0,0,0,0) >= today)
+ .map(r => ({ ...r, topicName: topic.name, topicId: topic.id }))
+ ).sort((a, b) => new Date(a.date) - new Date(b.date));
+ }, [topics, today]);
+
+ const pendingRevisions = useMemo(() => {
+ return topics.flatMap(topic =>
+ topic.reviews
+ .filter(r => !r.completed && new Date(r.date).setHours(0,0,0,0) < today)
+ .map(r => ({ ...r, topicName: topic.name, topicId: topic.id }))
+ ).sort((a, b) => new Date(a.date) - new Date(b.date));
+ }, [topics, today]);
+
+ const RevisionList = ({ title, revisions, isPending }) => (
+
+
{title} ({revisions.length})
+ {revisions.length > 0 ? (
+
+ {revisions.map((rev, index) => (
+ -
+
+ {rev.topicName} - {new Date(rev.date).toLocaleDateString()}
+
+
+
+ ))}
+
+ ) : (
+
No {title.toLowerCase()} for now.
+ )}
+
+ );
+
+ return (
+
+
Spaced Repetition
+
+ setNewTopic(e.target.value)}
+ placeholder="Enter new topic to study"
+ className="flex-grow p-2 border border-yellow-300 rounded-lg bg-white/50 focus:ring-2 focus:ring-yellow-500 focus:outline-none"
+ />
+
+
+
+
+
+ );
+};
+
+const Countdown = () => {
+ const [endDate, setEndDate] = useLocalStorage('countdown:endDate', new Date(new Date().getFullYear() + 1, 4, 5).toISOString());
+ const [timeLeft, setTimeLeft] = useState({});
+
+ const calculateTimeLeft = useCallback(() => {
+ const difference = +new Date(endDate) - +new Date();
+ let timeLeftData = {};
+
+ if (difference > 0) {
+ timeLeftData = {
+ days: Math.floor(difference / (1000 * 60 * 60 * 24)),
+ hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
+ minutes: Math.floor((difference / 1000 / 60) % 60),
+ seconds: Math.floor((difference / 1000) % 60)
+ };
+ }
+ return timeLeftData;
+ }, [endDate]);
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ setTimeLeft(calculateTimeLeft());
+ }, 1000);
+ return () => clearTimeout(timer);
+ });
+
+ const timerComponents = Object.keys(timeLeft).map(interval => {
+ if (timeLeft[interval] === undefined) {
+ return null;
+ }
+ return (
+
+ {timeLeft[interval].toString().padStart(2, '0')}
+ {interval}
+
+ );
+ });
+
+ return (
+
+
Exam Countdown
+
+ {timerComponents.length ? timerComponents : Time's up!}
+
+
+
+ setEndDate(new Date(e.target.value).toISOString())}
+ className="p-2 border border-yellow-300 rounded-lg bg-white/50 focus:ring-2 focus:ring-yellow-500 focus:outline-none"
+ />
+
+
+ );
+};
+
+const TodoList = () => {
+ const [tasks, setTasks] = useLocalStorage('todo:tasks', []);
+ const [newTask, setNewTask] = useState('');
+
+ useEffect(() => {
+ // Missed-task recovery system
+ const today = new Date().toISOString().split('T')[0];
+ const updatedTasks = tasks.map(task => {
+ if (!task.completed && task.dueDate && task.dueDate < today) {
+ return { ...task, dueDate: today }; // Reschedule to today
+ }
+ return task;
+ });
+ if (JSON.stringify(tasks) !== JSON.stringify(updatedTasks)) {
+ setTasks(updatedTasks);
+ }
+ }, []);
+
+ const addTask = () => {
+ if (newTask.trim() === '') return;
+ const today = new Date().toISOString().split('T')[0];
+ setTasks([...tasks, { id: Date.now(), text: newTask, completed: false, dueDate: today }]);
+ setNewTask('');
+ };
+
+ const toggleTask = (id) => {
+ setTasks(tasks.map(task => task.id === id ? { ...task, completed: !task.completed } : task));
+ };
+
+ const removeTask = (id) => {
+ setTasks(tasks.filter(task => task.id !== id));
+ };
+
+ return (
+
+
To-Do List
+
+ setNewTask(e.target.value)}
+ onKeyPress={(e) => e.key === 'Enter' && addTask()}
+ placeholder="Add a new task..."
+ className="flex-grow p-2 border border-yellow-300 rounded-lg bg-white/50 focus:ring-2 focus:ring-yellow-500 focus:outline-none"
+ />
+
+
+
+ {tasks.map(task => (
+ -
+ toggleTask(task.id)}
+ className={`cursor-pointer flex-grow ${task.completed ? 'line-through text-gray-500' : 'text-gray-800'}`}
+ >
+ {task.text}
+
+
+
+ ))}
+
+
+ );
+};
+
+const MarksCalculator = () => {
+ const [mode, setMode] = useState('sectional'); // sectional, mock
+ const [history, setHistory] = useLocalStorage('marks:history', []);
+
+ const SectionalCalculator = () => {
+ const subjects = ['English', 'Current Affairs/GK', 'Legal Reasoning', 'Logical Reasoning', 'Quantitative Techniques'];
+ const [data, setData] = useState(
+ subjects.reduce((acc, subject) => ({ ...acc, [subject]: { total: '', attempted: '', correct: '', wrong: '', time: '' } }), {})
+ );
+ const [results, setResults] = useState(null);
+
+ const calculate = () => {
+ let totalMarks = 0;
+ const newResults = {};
+ subjects.forEach(subject => {
+ const { correct, wrong, time } = data[subject];
+ const marks = (Number(correct) || 0) * 1 - (Number(wrong) || 0) * 0.25;
+ newResults[subject] = { marks };
+
+ if (correct > 0 && time > 0) {
+ const timePerCorrect = time / correct;
+ if (timePerCorrect > 1.5) { // Example threshold: 1.5 mins per correct answer
+ newResults[subject].feedback = "Good accuracy, but work on your speed.";
+ } else {
+ newResults[subject].feedback = "Excellent! Great accuracy and speed.";
+ }
+ } else {
+ newResults[subject].feedback = "Enter data to get feedback.";
+ }
+ totalMarks += marks;
+ });
+ newResults.total = totalMarks;
+ setResults(newResults);
+
+ setHistory([...history, { type: 'sectional', date: new Date().toLocaleDateString(), score: totalMarks, details: data }]);
+ };
+
+ return (
+