Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

made changes to trivia gen form. added an overall theme and ability t… #20

Merged
merged 1 commit into from
May 8, 2024
Merged
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
1 change: 1 addition & 0 deletions trivia-forge/frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ h2 {

.CardPadding {
margin: 20px;
padding: 10px;
background-color: bisque;
}

Expand Down
17 changes: 17 additions & 0 deletions trivia-forge/frontend/src/Components/Categories.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from "react";
import Questions from "../Components/Questions";

function Categories({ category }) {
let questions = category.questions;
return (
<div>
<h2>{category.name}</h2>
{questions.map((question, index) => {
return (
<Questions key={index} data={question} />
);
})}
</div>
);
}
export default Categories;
2 changes: 1 addition & 1 deletion trivia-forge/frontend/src/Components/Choices.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { Choice } from "../Model/Choice";


function Choices({ choices }) {
return (
Expand Down
3 changes: 2 additions & 1 deletion trivia-forge/frontend/src/Components/Questions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ function Questions({ data }) {
<textarea className="form-control" defaultValue={data.hint}></textarea>
</div>
</Card>
</div>

</div >
)
}
export default Questions;
5 changes: 3 additions & 2 deletions trivia-forge/frontend/src/Model/Game.jsx
Original file line number Diff line number Diff line change
@@ -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;
}
Expand All @@ -12,8 +13,8 @@ export class Game {

toJsonObject() {
return {
id: this.id,
name: this.name,
theme: this.theme,
userID: this.userID
}
}
Expand Down
208 changes: 141 additions & 67 deletions trivia-forge/frontend/src/Pages/TriviaGenPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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); }
}
Expand All @@ -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
Expand All @@ -93,43 +124,86 @@ function TriviaGenPage() {
<h1>
Trivia Generator
</h1>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="triviaTitle">Number of Questions:</label>
<input
type="number"
value={numberOfQuestions}
onChange={e => setNumberOfQuestions(Math.min(10, Math.max(1, parseInt(e.target.value, 10))))}
className="form-control"
id="triviaTitle"
placeholder="Number of Questions"
/>
</div>
<div className="form-group">
<label htmlFor="triviaCategory">Category:</label>
<input
type="text"
value={category}
onChange={e => setCategory(e.target.value)}
className="form-control"
id="triviaCategory"
placeholder="Category"
/>
</div>
<div className="form-group">
<label htmlFor="multipleChoice">Include Multiple Choice Answers:</label>
<input
type="checkbox"
checked={isMultipleChoice}
onChange={e => setIsMultipleChoice(e.target.value)}
//className="form-control"
id="multipleChoice"
/>
</div>
<button type="submit" className="btn btn-primary">Generate</button>
</form>

</div>
<Card>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="triviaTitle">Title:</label>
<input
type="text"
value={Title}
onChange={e => setTitle(e.target.value)}
className="form-control"
id="triviaTitle"
placeholder="Title"
/>
</div>

<div className="form-group">
<label htmlFor="triviaTitle">Theme:</label>
<input
type="text"
value={Theme}
onChange={e => setTheme(e.target.value)}
className="form-control"
id="triviaTheme"
placeholder="Theme"
/>
</div>

<div className="form-group">
<label htmlFor="triviaTitle">Number of Questions per Category:</label>
<input
type="number"
value={numberOfQuestions}
onChange={e => setNumberOfQuestions(Math.min(10, Math.max(1, parseInt(e.target.value, 10))))}
className="form-control"
id="triviaTitle"
placeholder="Number of Questions"
/>
</div>

<div className="form-group">

{categories.map((category, index) => (
<Card key={index} className="CardPadding">
<div >
<label>Category Name:</label>
<input
type="text"
value={category.name}
onChange={e => handleChangeCategoryDetail(index, 'name', e.target.value)}
className="form-control"
id="categoryName"
placeholder="Category"
/>

<br />
</div>
</Card>

))}

</div>
<button type="button" className="btn btn-secondary" onClick={handleAddCategory}>Add Category</button>



<div className="form-group">
<label htmlFor="multipleChoice">Include Multiple Choice Answers:</label>
<input
type="checkbox"
checked={isMultipleChoice}
onChange={e => setIsMultipleChoice(e.target.value)}
//className="form-control"
id="multipleChoice"
/>
</div>

<button type="submit" className="btn btn-primary">Generate</button>
</form >
</Card >

</div >
);

}
Expand Down
9 changes: 4 additions & 5 deletions trivia-forge/frontend/src/Pages/TriviaReviewPage.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
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() {
// Reference: https://reactrouter.com/en/main/hooks/use-location
// 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 (
<div>
<h1>Review and Edit Trivia Questions</h1>

{questions.map((q, index) => (
<Questions key={index} data={q} />
{categories.map((cat, index) => (
<Categories key={index} category={cat} />

))}
<Button variant="primary" size="lg" block>
Expand Down