Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
5 changes: 5 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/easy-study-web-app-main.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 55 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,55 @@
# About The Hackathon
The MoroccoAI InnovAI Hackathon is a unique opportunity for AI enthusiasts, professionals, and innovators to collaborate and create transformative AI-based solutions addressing real-life challenges in Morocco and across Africa. As part of the annual MoroccoAI Annual Conference, this hackathon is set under the theme “Driving the Future of Innovation Through AI”, inspiring participants to harness AI’s capabilities to make a meaningful societal impact. Participants will join teams to develop Proof of Concepts (PoCs) using applications or APIs that address challenges in various domains. Education, Healthcare, Environment, Finance or Customer Services .

In line with MoroccoAI’s mission, this hackathon centers around “Driving the Future of Innovation Through AI”. AI has the power to redefine industries, address community needs, and propel sustainable growth. Through this event, participants will dive into AI’s potential by developing impactful solutions that address challenges unique to Morocco and Africa in fields such as agriculture, education, health, and finance, fostering innovation in response to real-world needs.

# The Challenge
Connect with the MoroccoAI community, join teams and brainstorm ideas then come up with a project that leverages AI in 5 areas of focus:
* Innovation
* Healthcare
* Environment
* Finance
* CustomerServices

# Mentorship
Join the Hackathon server on discord and meet the mentors to learn more about their proposed projects.

# Why should you participate in this Hackathon?
* Hands-on experience in AI project development that targets relevant issues in Morocco and Africa.
* Mentorship and networking opportunities with experts and peers in the AI community.
* Showcase their solutions to a jury of AI specialists at the awards ceremony, creating visibility and opportunities for further development.
* Win great prizes offered by MoroccoAI's sponsors
* Obtain your MoroccoAI certificate of recognition

# For more information
https://morocco.ai/events/conferences/MoroccoAI-Conference-2024/pages/hackathon.html


# Easy Study Web App

This project is a web application designed to enhance student learning by generating quizzes, flashcards, courses , questions answers based on the provided topics.

---

## Abstract

### Background and Problem Statement
In today's fast-paced education environment, students often struggle to find efficient ways to revise and consolidate their knowledge. Manually creating study materials such as quizzes or flashcards can be time-consuming and ineffective. Additionally, locating relevant supplemental resources like guided courses is a fragmented process.

### Impact and Proposed Solution
The **AI Study web app** addresses these issues by automating the creation of personalized study aids. Using advanced AI techniques and efficient database management, the app generates topic-specific quizzes, flashcards, q&a and curates educational courses recommendations, saving students valuable time and enhancing their learning experience.

### Project Outcomes and Deliverables
- **Quizzes and Flashcards**: Automatically generated based on user-submitted topics or keywords.
- **Educational Course Recommendations**: AI-curated relevant courses for deeper understanding.
- **Interactive User Interface**: A responsive and intuitive interface for students to access study aids effortlessly.
- **Integration with Next.js, Dizzle ORM, and Ingest**: Ensures scalability, efficiency, and real-time data handling.



## Technologies Used

- **Next.js**: React framework for server-side rendering and static site generation.
- **Dizzle ORM**: Object-relational mapping (ORM) for database management.
- **Ingest**: For data ingestion and streaming.
- **Gemini API**: For retrieving personalized educational content and resources.
- **OpenAI**: For generating quizzes, flashcards, and natural language processing tasks.
- Other tools: Node.js, npm.

---

## Getting Started

Follow the steps below to set up and run the project locally.

### Prerequisites

Ensure you have the following installed on your system:

- [Node.js](https://nodejs.org/) (v16 or later)
- [npm](https://www.npmjs.com/)
- A database supported by Dizzle ORM (e.g., PostgreSQL, MySQL, etc.)

---

## Setup and Installation

1. **Clone the Repository**
```bash
git clone https://github.com/youssefhergal/2024-InnovAI-Hackathon.git
cd easy-study-web-app-main
9 changes: 9 additions & 0 deletions app/(auth)/sign-in/[[...sign-in]]/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { SignIn } from '@clerk/nextjs'

export default function Page() {
return (
<div className='flex items-center justify-center h-screen'>
<SignIn />
</div>
)
}
5 changes: 5 additions & 0 deletions app/(auth)/sign-up/[[...sign-up]]/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SignUp } from '@clerk/nextjs'

export default function Page() {
return <SignUp />
}
3 changes: 3 additions & 0 deletions app/_context/CourseCountContext.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createContext } from "react";

export const CourseCountContext=createContext();
30 changes: 30 additions & 0 deletions app/api/courses/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { db } from "@/configs/db";
import { STUDY_MATERIAL_TABLE } from "@/configs/schema";
import { desc, eq } from "drizzle-orm";
import { NextResponse } from "next/server";

export async function POST(req) {

const {createdBy}=await req.json();

const result=await db.select().from(STUDY_MATERIAL_TABLE)
.where(eq(STUDY_MATERIAL_TABLE.createdBy,createdBy))
.orderBy(desc(STUDY_MATERIAL_TABLE.id))


return NextResponse.json({result:result});

}

export async function GET(req) {

const reqUrl=req.url;
const {searchParams}=new URL(reqUrl);
const courseId=searchParams?.get('courseId');

const course=await db.select().from(STUDY_MATERIAL_TABLE)
.where(eq(STUDY_MATERIAL_TABLE?.courseId,courseId));

return NextResponse.json({result:course[0]})

}
16 changes: 16 additions & 0 deletions app/api/create-user/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { inngest } from "@/inngest/client";
import { NextResponse } from "next/server";

export async function POST(req) {

const {user}=await req.json();

const result=await inngest.send({
name:'user.create',
data:{
user:user
}
})

return NextResponse.json({result:result})
}
81 changes: 81 additions & 0 deletions app/api/generate-course-outline/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { courseOutlineAIModel } from "@/configs/AiModel";
import { db } from "@/configs/db";
import { STUDY_MATERIAL_TABLE } from "@/configs/schema";
import { inngest } from "@/inngest/client";
import { NextResponse } from "next/server";

export async function POST(req) {

const {courseId,topic,courseType,difficultyLevel,createdBy}=await req.json();

const PROMPT = `
Generate a comprehensive study material outline for the topic: "${topic}".
Ensure the material is suitable for a difficulty level of "${difficultyLevel}".

The output should include the following:
1. **Course Title**: Provide a concise, engaging, and descriptive title for the course.
2. **Course Summary**: Write a brief summary of the course, highlighting its objectives, target audience, and key takeaways.
3. **List of Chapters** (Maximum of 3):
- Include a creative and descriptive title for each chapter.
- Provide a brief summary of each chapter (2-3 sentences).
- Suggest an appropriate emoji icon to represent each chapter.
4. **Topics List**: Include a list of topics covered in each chapter to give a clear structure to the material.

**Important**:
- The output must be generated in the same language as the topic. For example, if the topic is in French, generate the content in French; if in Arabic, generate it in Arabic, and so on. Adjust the tone and phrasing to suit the language context appropriately.

Ensure the output is returned in **valid JSON format**, structured as follows:
{
"title": "Course Title",
"summary": "Course Summary",
"chapters": [
{
"title": "Chapter 1 Title",
"summary": "Chapter 1 Summary",
"emoji": "📘",
"topics": ["Topic 1", "Topic 2", "Topic 3"]
},
{
"title": "Chapter 2 Title",
"summary": "Chapter 2 Summary",
"emoji": "📙",
"topics": ["Topic 1", "Topic 2", "Topic 3"]
},
{
"title": "Chapter 3 Title",
"summary": "Chapter 3 Summary",
"emoji": "📗",
"topics": ["Topic 1", "Topic 2", "Topic 3"]
}
]
}

Focus on creating a user-friendly and engaging output that makes the material easy to understand and visually appealing.
`;

// Generate Course Layout using AI
const aiResp=await courseOutlineAIModel.sendMessage(PROMPT);
const aiResult= JSON.parse(aiResp.response.text());

// Save the result along with User Input
const dbResult=await db.insert(STUDY_MATERIAL_TABLE).values({
courseId:courseId,
courseType:courseType,
createdBy:createdBy,
topic:topic,
courseLayout:aiResult
}).returning({resp:STUDY_MATERIAL_TABLE})

//Trigger the Inngest function to generate chapter notes

inngest.send({
name:'notes.generate',
data:{
course:dbResult[0].resp
}
});
// console.log(result);

return NextResponse.json({result:dbResult[0]})

}
Empty file added app/api/generate/route.js
Empty file.
16 changes: 16 additions & 0 deletions app/api/inngest/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { serve } from "inngest/next";
import { inngest } from "../../../inngest/client";
import { CreateNewUser, GenerateNotes, GenerateStudyTypeContent, helloWorld } from "@/inngest/functions";
export const runtime = 'edge';
// Create an API that serves zero functions
export const { GET, POST, PUT } = serve({
client: inngest,
streaming:'allow',
functions: [
/* your functions will be passed here later! */
helloWorld,
CreateNewUser,
GenerateNotes,
GenerateStudyTypeContent
],
});
64 changes: 64 additions & 0 deletions app/api/study-type-content/route.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { db } from "@/configs/db";
import { STUDY_TYPE_CONTENT_TABLE } from "@/configs/schema";
import { inngest } from "@/inngest/client";
import { NextResponse } from "next/server";

// Function to get the prompt based on the study type
function getPromptByType(type, chapters) {
switch (type) {
case 'Flashcard':
return `Generate flashcards on the topic: ${chapters} in JSON format with "front" and "back" content. Limit to a maximum of 15 flashcards.`;

case 'Question/Answer' :
return `Generate a Question and Answer list on the topic: ${chapters} in JSON format with the following structure:
{
"questions": [
{
"question": "What is machine learning?",
"answer": "Machine learning (ML) is a branch of artificial intelligence (AI) and computer science which focuses on the use of data and algorithms to imitate the way that humans learn, gradually improving its accuracy."
},
...
]
}
Limit the number of qaPairs to a maximum of 10. Ensure each question is clear, and the answers are detailed and accurate.`;

case 'Quiz':
return `Generate a quiz on the topic: ${chapters} in JSON format with questions, multiple-choice options, and the correct answer for each. Limit to a maximum of 10 questions.`;

default:
throw new Error("Invalid type provided");
}
}

export async function POST(req) {
const { chapters, courseId, type } = await req.json();

try {
// Get the appropriate prompt using the helper function
const PROMPT = getPromptByType(type, chapters);
console.log(PROMPT)

// Insert record into the database and set status to "Generating..."
const result = await db.insert(STUDY_TYPE_CONTENT_TABLE).values({
courseId: courseId,
type: type,
}).returning({ id: STUDY_TYPE_CONTENT_TABLE.id });

// Trigger Inngest function with the generated prompt
await inngest.send({
name: 'studyType.content',
data: {
studyType: type,
prompt: PROMPT,
courseId: courseId,
recordId: result[0].id,
},
});

// Return the newly created record ID
return NextResponse.json(result[0].id);
} catch (error) {
// Handle invalid type or other errors
return NextResponse.json({ error: error.message }, { status: 400 });
}
}
Loading