From 546fdf41e247a645a31832e5e9d8ff0d381b8323 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 6 May 2024 16:04:03 -0700 Subject: [PATCH] made changes to trivia gen form. added an overall theme and ability to have multiple categories for a game --- trivia-forge/frontend/src/App.css | 1 + .../frontend/src/Components/Categories.jsx | 17 ++ .../frontend/src/Components/Choices.jsx | 2 +- .../frontend/src/Components/Questions.jsx | 3 +- trivia-forge/frontend/src/Model/Game.jsx | 5 +- .../frontend/src/Pages/TriviaGenPage.jsx | 208 ++++++++++++------ .../frontend/src/Pages/TriviaReviewPage.jsx | 9 +- 7 files changed, 169 insertions(+), 76 deletions(-) create mode 100644 trivia-forge/frontend/src/Components/Categories.jsx diff --git a/trivia-forge/frontend/src/App.css b/trivia-forge/frontend/src/App.css index df652cc9..066132a8 100644 --- a/trivia-forge/frontend/src/App.css +++ b/trivia-forge/frontend/src/App.css @@ -110,6 +110,7 @@ h2 { .CardPadding { margin: 20px; + padding: 10px; background-color: bisque; } diff --git a/trivia-forge/frontend/src/Components/Categories.jsx b/trivia-forge/frontend/src/Components/Categories.jsx new file mode 100644 index 00000000..0e2ff42a --- /dev/null +++ b/trivia-forge/frontend/src/Components/Categories.jsx @@ -0,0 +1,17 @@ +import React from "react"; +import Questions from "../Components/Questions"; + +function Categories({ category }) { + let questions = category.questions; + return ( +
+

{category.name}

+ {questions.map((question, index) => { + return ( + + ); + })} +
+ ); +} +export default Categories; \ No newline at end of file diff --git a/trivia-forge/frontend/src/Components/Choices.jsx b/trivia-forge/frontend/src/Components/Choices.jsx index 02c090a9..15ad2bc7 100644 --- a/trivia-forge/frontend/src/Components/Choices.jsx +++ b/trivia-forge/frontend/src/Components/Choices.jsx @@ -1,5 +1,5 @@ import React from "react"; -import { Choice } from "../Model/Choice"; + function Choices({ choices }) { return ( diff --git a/trivia-forge/frontend/src/Components/Questions.jsx b/trivia-forge/frontend/src/Components/Questions.jsx index d1b5895e..3daaf5cf 100644 --- a/trivia-forge/frontend/src/Components/Questions.jsx +++ b/trivia-forge/frontend/src/Components/Questions.jsx @@ -24,7 +24,8 @@ function Questions({ data }) { - + + ) } export default Questions; \ No newline at end of file diff --git a/trivia-forge/frontend/src/Model/Game.jsx b/trivia-forge/frontend/src/Model/Game.jsx index 9b5be3b4..9cacab70 100644 --- a/trivia-forge/frontend/src/Model/Game.jsx +++ b/trivia-forge/frontend/src/Model/Game.jsx @@ -1,7 +1,8 @@ export class Game { - constructor(name, date, userID = null) { + constructor(name, theme, userID = null) { this.id = null; this.name = name; + this.theme = theme; this.categories = []; this.userID = userID; } @@ -12,8 +13,8 @@ export class Game { toJsonObject() { return { - id: this.id, name: this.name, + theme: this.theme, userID: this.userID } } diff --git a/trivia-forge/frontend/src/Pages/TriviaGenPage.jsx b/trivia-forge/frontend/src/Pages/TriviaGenPage.jsx index c3e4f09d..dbb96fb0 100644 --- a/trivia-forge/frontend/src/Pages/TriviaGenPage.jsx +++ b/trivia-forge/frontend/src/Pages/TriviaGenPage.jsx @@ -5,6 +5,7 @@ import { useNavigate } from "react-router-dom"; import { Question } from "../Model/Question"; import { Choice } from "../Model/Choice"; import { Category } from "../Model/Category"; +import { Card } from "react-bootstrap"; // initialize openai client using configuration specified in vite environment variables @@ -18,41 +19,71 @@ function TriviaGenPage() { // state hooks for managaing number of questions and catergory input by user const [numberOfQuestions, setNumberOfQuestions] = useState(''); const [category, setCategory] = useState(''); - const [isMultipleChoice, setIsMultipleChoice] = useState(false); + const [Title, setTitle] = useState(''); + const [Theme, setTheme] = useState(''); + const [categories, setCategories] = useState([]); + const [isMultipleChoice, setIsMultipleChoice] = useState(true); const navigate = useNavigate(); + const handleAddCategory = () => { + const newCategory = { name: '' }; + setCategories([...categories, newCategory]); + }; + const handleChangeCategoryDetail = (index, field, value) => { + const newCategories = categories.map((category, idx) => { + if (idx === index) { + return { ...category, [field]: value }; + } + return category; + }); + setCategories(newCategories); + }; const handleSubmit = async (event) => { event.preventDefault(); // prevent default form submission behavior(browser reload) - //for each category - let prompt = `Generate ${numberOfQuestions} trivia questions about ${category}.`; - if (isMultipleChoice) { - prompt += "Each question should be in the format Question:...\nChoice:...\nChoice:...\nChoice:...\nChoice:...\nAnswer:...\nHint:...\n---\nQuestion:... ect. include four multiple-choice options"; - } else { - prompt += "Each question should be in the format \nQuestion:...\nAnswer:...\n---\nQuestion:... ect."; + + let responses = [] + + for (let i = 0; i < categories.length; i++) { + let prompt = `Generate ${numberOfQuestions} trivia questions that have an overall theme of ${Theme} about ${categories[i].name}.`; + if (isMultipleChoice) { + prompt += "Each question should be in the format Question:...\nChoice:...\nChoice:...\nChoice:...\nChoice:...\nAnswer:...\nHint:...\n---\nQuestion:... ect. include four multiple-choice options"; + } else { + prompt += "Each question should be in the format \nQuestion:...\nAnswer:...\n---\nQuestion:... ect."; + } + + // api call + try { + + // API call to OpenAI + const completion = await openai.chat.completions.create({ + model: "gpt-3.5-turbo", + messages: [{ role: "user", content: prompt }], + // adjust and use token limit if necessary + // max_tokens: 200 + // implment and adjust temperature if needed + // temperature scale is 0-1 and used to tune randomness of output + // temperature: .5 + }); + let response = completion.choices[0].message.content.split('\n'); + + responses.push(response); + } + catch (error) { + console.error('Error calling OpenAI API:', error); + } } + //create a new game and category object and add category to game + let game = new Game(Title, Theme); - // api call - try { - - // API call to OpenAI - const completion = await openai.chat.completions.create({ - model: "gpt-3.5-turbo", - messages: [{ role: "user", content: prompt }], - // adjust and use token limit if necessary - // max_tokens: 200 - // implment and adjust temperature if needed - // temperature scale is 0-1 and used to tune randomness of output - // temperature: .5 - }); - //create a new game and category object and add category to game - let game = new Game(); - let newCategory = new Category(category); + for (let i = 0; i < categories.length; i++) { + let newCategory = new Category(categories[i].name); + console.log(newCategory.name); game.addCategory(newCategory); //parse response from API - let sections = completion.choices[0].message.content.split('\n'); // store trivia questions + let sections = responses[i]; // store trivia questions for (let i = 0; i < sections.length; i++) { if (sections[i] === '') { sections.splice(i, 1); } } @@ -76,15 +107,15 @@ function TriviaGenPage() { for (let i = 0; i < choices.length; i++) { newQuestion.addChoice(choices[i]); } + } - } - // state property to pass data as object to new route - navigate('/review', { state: { game } }); - //console.log(completion.choices[0].message); - } catch (error) { - console.error('Error calling OpenAI API:', error); } + // state property to pass data as object to new route + navigate('/review', { state: { game } }); + //console.log(completion.choices[0].message); + + }; // render component as a form @@ -93,43 +124,86 @@ function TriviaGenPage() {

Trivia Generator

-
-
- - setNumberOfQuestions(Math.min(10, Math.max(1, parseInt(e.target.value, 10))))} - className="form-control" - id="triviaTitle" - placeholder="Number of Questions" - /> -
-
- - setCategory(e.target.value)} - className="form-control" - id="triviaCategory" - placeholder="Category" - /> -
-
- - setIsMultipleChoice(e.target.value)} - //className="form-control" - id="multipleChoice" - /> -
- -
- - + +
+
+ + setTitle(e.target.value)} + className="form-control" + id="triviaTitle" + placeholder="Title" + /> +
+ +
+ + setTheme(e.target.value)} + className="form-control" + id="triviaTheme" + placeholder="Theme" + /> +
+ +
+ + setNumberOfQuestions(Math.min(10, Math.max(1, parseInt(e.target.value, 10))))} + className="form-control" + id="triviaTitle" + placeholder="Number of Questions" + /> +
+ +
+ + {categories.map((category, index) => ( + +
+ + handleChangeCategoryDetail(index, 'name', e.target.value)} + className="form-control" + id="categoryName" + placeholder="Category" + /> + +
+
+
+ + ))} + +
+ + + + +
+ + setIsMultipleChoice(e.target.value)} + //className="form-control" + id="multipleChoice" + /> +
+ + +
+
+ + ); } diff --git a/trivia-forge/frontend/src/Pages/TriviaReviewPage.jsx b/trivia-forge/frontend/src/Pages/TriviaReviewPage.jsx index dfd7607f..3e16ea85 100644 --- a/trivia-forge/frontend/src/Pages/TriviaReviewPage.jsx +++ b/trivia-forge/frontend/src/Pages/TriviaReviewPage.jsx @@ -1,6 +1,6 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; // used to access passed state -import Questions from '../Components/Questions'; +import Categories from '../Components/Categories'; import { Button } from 'react-bootstrap'; function TriviaReviewPage() { @@ -8,14 +8,13 @@ function TriviaReviewPage() { // pulls object from state property in TriviaGenPage const location = useLocation(); const { game } = location.state; - let category = game.categories[0]; - let questions = category.questions; + let categories = game.categories; return (

Review and Edit Trivia Questions

- {questions.map((q, index) => ( - + {categories.map((cat, index) => ( + ))}