Skip to content

Commit

Permalink
Merge pull request #20 from emmanueposu/jbranch4
Browse files Browse the repository at this point in the history
made changes to trivia gen form. added an overall theme and ability t…
  • Loading branch information
demuthsa authored May 8, 2024
2 parents abf2038 + 546fdf4 commit a5c4380
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 76 deletions.
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

0 comments on commit a5c4380

Please sign in to comment.