Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
intls authored Jul 4, 2024
0 parents commit 4b9092b
Show file tree
Hide file tree
Showing 18 changed files with 10,148 additions and 0 deletions.
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# DappyKit + Farcaster + Vercel Template

This is a Quiz Typescript Frame template for Farcaster integrated with DappyKit. The template is ready to deploy on Vercel. A KV storage must be created to store user sessions for the project to work.

In the `./quiz.json` file, a list of questions and answers is stored.
The project is configured in Vercel through environment variables. Here is the list of variables:
- `APP_OWNER_FID` - a unique user number in Farcaster, the application administrator.
- `APP_PK` - an ETH-compatible private key in 0x format for signing messages.
- `APP_SHARE_URL` - the link to the Frame itself after deployment, needed to share the Quiz with other users.
- `AUTH_SERVICE_ADDRESS` - **not required**. Auth signer address from https://github.com/DappyKit/farcaster-auth.
- `APP_AUTH_URL` - **not required**. The link to the authorization Frame. You can provide your own if the standard one doesn't fit.
- `APP_TITLE` - **not required**. The title of your application.
- `KV_NAMESPACE` - **not required**. A unique namespace for your application. Required only if multiple applications use the same KV storage.

## Video Tutorial

[![Watch the tutorial](https://img.youtube.com/vi/KMyvM20NDx8/0.jpg)](https://www.youtube.com/watch?v=KMyvM20NDx8)

## Create your custom Quiz with ChatGPT

🆓 Use this [prompt](./GPT_PROMPT.md).

🆓 If you are an **OLD** free ChatGPT user, you can generate a correct `quiz.json` file using this chat: https://chatgpt.com/g/g-UFjeBIRpE-dappykit-quiz-for-farcaster

💸 If you have a ChatGPT subscription, you can generate the entire project with the quiz in this chat: https://chatgpt.com/g/g-mxV7W9Rgi-dappykit-quiz-frame-for-farcaster

To generate the quiz, you need to specify the topic of the questions, and ChatGPT will do the rest for you. You can also specify the number of questions you need to create. By default, the chat will generate 30 questions.


## Installation
```
npm ci
npm run dev
```

Go to http://localhost:5173/api/dev
128 changes: 128 additions & 0 deletions __tests__/quiz.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { Quiz, QuizStructure, Question, CheckResult } from '../api/quiz/index.ts'

function generateQuestion(correctAnswerIndex: number): Question {
const numAnswers = Quiz.expectedAnswersCount
const question: Question = {
question: 'Random question?',
answers: [],
correctAnswerIndex: correctAnswerIndex,
}

// Generate random answers
for (let i = 0; i < numAnswers; i++) {
question.answers.push(`Answer ${i + 1}`)
}

return question
}

describe('Quiz', () => {
let quizStructure: QuizStructure

beforeEach(() => {
quizStructure = {
questions: [
generateQuestion(2), // Correct answer at index 2
generateQuestion(1), // Correct answer at index 1
],
}
})

it('should validate quiz structure', () => {
expect(Quiz.validateQuizStructure(quizStructure)).toBe(true)
})

it('should check correct answer', () => {
const quiz = new Quiz(quizStructure)
const result: CheckResult = quiz.check(2)
expect(result.isCorrect).toBe(true) // Correct answer for first question
expect(result.points).toBe(1)
expect(result.nextQuestionId).toBe(1)
})

it('should check incorrect answer', () => {
const quiz = new Quiz(quizStructure)
const result: CheckResult = quiz.check(1)
expect(result.isCorrect).toBe(false) // Incorrect answer for first question
expect(result.points).toBe(0)
expect(result.nextQuestionId).toBe(1)
})

it('should handle last question', () => {
const quiz = new Quiz(quizStructure, 1) // Start with second question
const result: CheckResult = quiz.check(1)
expect(result.isCorrect).toBe(true) // Correct answer for second question
expect(result.points).toBe(1)
expect(result.nextQuestionId).toBeNull()
})

it('should return false for invalid quiz structure', () => {
const invalidQuizStructure: QuizStructure = {
questions: [
generateQuestion(1), // Correct answer at index 1
],
}
invalidQuizStructure.questions[0].answers.pop() // make the number of answers less than expected
expect(Quiz.validateQuizStructure(invalidQuizStructure)).toBe(false)
})

it('should handle empty quiz structure', () => {
const emptyQuizStructure: QuizStructure = { questions: [] }
expect(() => new Quiz(emptyQuizStructure)).toThrow()
})

it('should not accept answer index out of bounds', () => {
const quiz = new Quiz(quizStructure)
const result: CheckResult = quiz.check(10)
expect(result.isCorrect).toBe(false)
expect(result.points).toBe(0)
expect(result.nextQuestionId).toBe(1)
})

it('should handle questions with the same answers', () => {
const sameAnswersQuizStructure: QuizStructure = {
questions: [
{
question: 'Which one?',
answers: ['A', 'A', 'A'],
correctAnswerIndex: 1,
},
],
}
const quiz = new Quiz(sameAnswersQuizStructure)
const result: CheckResult = quiz.check(1)
expect(result.isCorrect).toBe(true)
expect(result.points).toBe(1)
expect(result.nextQuestionId).toBeNull()
})

it('should handle negative answer index', () => {
const quiz = new Quiz(quizStructure)
const result: CheckResult = quiz.check(-1)
expect(result.isCorrect).toBe(false)
expect(result.points).toBe(0)
expect(result.nextQuestionId).toBe(1)
})

it('should return false for check if no current question', () => {
const emptyQuizStructure: QuizStructure = { questions: [] }
expect(() => new Quiz(emptyQuizStructure)).toThrow()
})

it('should handle quiz with maximum points', () => {
const maxPointsQuizStructure: QuizStructure = {
questions: [generateQuestion(0), generateQuestion(1), generateQuestion(2), generateQuestion(1)],
}
const quiz = new Quiz(maxPointsQuizStructure)
quiz.check(0)
quiz.currentQuestionIndex++
quiz.check(1)
quiz.currentQuestionIndex++
quiz.check(2)
quiz.currentQuestionIndex++
const result: CheckResult = quiz.check(1)
expect(result.points).toBe(1)
expect(result.isCorrect).toBe(true)
expect(result.nextQuestionId).toBeNull()
})
})
Loading

0 comments on commit 4b9092b

Please sign in to comment.