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
29 changes: 24 additions & 5 deletions client/src/components/blackout/Blackout.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import React, { useState } from "react";
import { Button } from "@chakra-ui/react";
import { RiEyeCloseLine } from "react-icons/ri";
import { MdOutlineMenuBook } from "react-icons/md";
import { MdOutlineRestartAlt } from "react-icons/md";
import { MdContentCopy } from "react-icons/md";
import {
MdOutlineMenuBook,
MdOutlineRestartAlt,
MdContentCopy,
} from "react-icons/md";
import type { PoemSnapshot } from "../../types";

interface BlackoutProps {
onSubmit?: () => void;
selectedWordIndexes: number[];
setSelectedWordIndexes: React.Dispatch<React.SetStateAction<number[]>>;
setPoemSnapshots: React.Dispatch<React.SetStateAction<PoemSnapshot[]>>;
}

const BlackoutPoetry: React.FC<BlackoutProps> = ({
onSubmit,
selectedWordIndexes,
setSelectedWordIndexes,
setPoemSnapshots,
}) => {
const [passageText] = useState(
"Twilight settled over Zuckerman’s barn, and a feeling of peace. Fern knew it was almost suppertime but she couldn’t bear to leave. Swallows passed on silent wings, in and out of the doorways, bringing food to their young ones. From across the road a bird sang “Whippoorwill, whippoorwill!” Lurvy sat down under an apple tree and lit his pipe; the animals sniffed the familiar smell of strong tobacco. Wilbur heard the trill of the tree toad and the occasional slamming of the kitchen door. All these sounds made him feel comfortable and happy, for he loved life and loved to be a part of the world on a summer evening. But as he lay there he remembered what the old sheep had told him. The thought of death came to him and he began to tremble with fear."
Expand All @@ -28,18 +33,32 @@ const BlackoutPoetry: React.FC<BlackoutProps> = ({

const toggleSelect = (index: number) => {
setSelectedWordIndexes((prev) => {
let newIndexes: number[];

if (prev.includes(index)) {
// Remove index
return prev.filter((i) => i !== index);
newIndexes = prev.filter((i) => i !== index);
} else {
// Add index
return [...prev, index];
newIndexes = [...prev, index];
}

const newSnapshot: PoemSnapshot = {
indexes: newIndexes,
timestamp: new Date(),
};

setPoemSnapshots((prevSnapshots) => [...prevSnapshots, newSnapshot]);

return newIndexes;
});
};

const resetSelection = () => {
setSelectedWordIndexes([]);

const newSnapshot: PoemSnapshot = { indexes: [], timestamp: new Date() };
setPoemSnapshots((prev) => [...prev, newSnapshot]);
};

return (
Expand Down
32 changes: 24 additions & 8 deletions client/src/components/chatbot/Chatbot.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState, useRef } from "react";
import { useEffect, useState, useRef, useMemo } from "react";
import { FiSend } from "react-icons/fi";
import { Button, Textarea } from "@chakra-ui/react";
import { nanoid } from "nanoid";
Expand All @@ -11,6 +11,7 @@ interface ChatTabProps {
messages: Message[];
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
stage: Stage;
selectedWordIndexes?: number[];
}

const systemMessageDefault = `
Expand All @@ -23,21 +24,23 @@ Your default style should be natural, chatty, and playful, rather than formal, r

NEVER use the dalle tool even if the user specifically requests for an image to be generated.

Blackout poetry is a form of poetry where given a passage, you select words from that passage to create a poem. Words must be selected in order as they appear in the passage, and selected words must appear in the passage. The passage is: Start Passage. Twilight settled over Zuckerman’s barn, and a feeling of peace. Fern knew it was almost suppertime but she couldn’t bear to leave. Swallows passed on silent wings, in and out of the doorways, bringing food to their young ones. From across the road a bird sang “Whippoorwill, whippoorwill!” Lurvy sat down under an apple tree and lit his pipe; the animals sniffed the familiar smell of strong tobacco. Wilbur heard the trill of the tree toad and the occasional slamming of the kitchen door. All these sounds made him feel comfortable and happy, for he loved life and loved to be a part of the world on a summer evening. But as he lay there he remembered what the old sheep had told him. The thought of death came to him and he began to tremble with fear. End Passage. The passage begins after "Start Passage." and ends before "End Passage.".',
Blackout poetry is a form of poetry where given a passage, you select words from that passage to create a poem. Words must be selected in order as they appear in the passage, and selected words must appear in the passage.

The user is tasked with creating a blackout poem from this passage. Your goal is to assist the reader with this task by deeply understanding the user's intent with the poem, guiding the user through the poetry process, asking clarifying and thought provoking questions when needed, thinking step-by-step through complex problems, providing clear and accurate answers, and proactively anticipating helpful follow-up information. There are two stages in this process, SPARK and WRITE. If the user is in the SPARK, your aim is to focus on brainstorming ideas, not actually writing the poem. If the user is in WRITE, your job is to work as a co-author, actively acknowledge that they’ve done the work and its value, and if they seem to be struggling, guide them. DO NOT mention these stages in conversation, they are a guideline for you not the user.

You MUST use this passage. Do not mention any other text, and always refer to the one given.

Do not write a blackout poem unless the user specifically requests for a poem to be generated.


`;

const passage =
"Twilight settled over Zuckerman’s barn, and a feeling of peace. Fern knew it was almost suppertime but she couldn’t bear to leave. Swallows passed on silent wings, in and out of the doorways, bringing food to their young ones. From across the road a bird sang “Whippoorwill, whippoorwill!” Lurvy sat down under an apple tree and lit his pipe; the animals sniffed the familiar smell of strong tobacco. Wilbur heard the trill of the tree toad and the occasional slamming of the kitchen door. All these sounds made him feel comfortable and happy, for he loved life and loved to be a part of the world on a summer evening. But as he lay there he remembered what the old sheep had told him. The thought of death came to him and he began to tremble with fear.";

export default function ChatTab({
messages,
setMessages,
stage,
selectedWordIndexes,
}: ChatTabProps) {
const chatContainerRef = useRef<HTMLDivElement>(null);

Expand All @@ -47,10 +50,23 @@ export default function ChatTab({
? `The user is in the SPARK stage.`
: `The user is in the WRITE stage.`);

const systemMessage = {
role: "system",
content: systemMessageStage,
};
const systemMessage = useMemo(() => {
const words = passage.split(/\s+/);
const selectedWords =
selectedWordIndexes
?.sort()
.map((i) => words[i])
.join(" ") || "";

return {
role: "system",
content:
systemMessageStage +
`The passage is: ${passage}, and the currently selected words are: ${
selectedWords || "none yet"
}`,
};
}, [selectedWordIndexes]);

const [isLLMLoading, setIsLLMLoading] = useState(false);
const [input, setInput] = useState("");
Expand Down
3 changes: 3 additions & 0 deletions client/src/components/shared/pages/multiPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface PageTemplateProps {
setMessages: React.Dispatch<React.SetStateAction<Message[]>>;
notes: string;
setNotes: React.Dispatch<React.SetStateAction<string>>;
selectedWordIndexes?: number[];
}

interface Button {
Expand All @@ -41,6 +42,7 @@ function MultiPageTemplate({
setMessages,
notes,
setNotes,
selectedWordIndexes,
}: PageTemplateProps) {
const [leftWidth, setLeftWidth] = useState(70); // %
const [topHeight, setTopHeight] = useState(70); // %
Expand Down Expand Up @@ -172,6 +174,7 @@ function MultiPageTemplate({
messages={messages}
setMessages={setMessages}
stage={stage}
selectedWordIndexes={selectedWordIndexes}
/>
</div>
</>
Expand Down
18 changes: 18 additions & 0 deletions client/src/pages/Captcha.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Button, Input } from "@chakra-ui/react";
import { toaster } from "../components/ui/toaster";
import { DataContext } from "../App";
import { ArtistCondition } from "../types";
import type { Poem } from "../types";

const TEST_CAPTCHA = "*TEST";

Expand Down Expand Up @@ -90,6 +91,23 @@ const Captcha = () => {
timeStamps: [...(userData?.data?.timeStamps ?? []), new Date()],
});
navigate("/consent");
} else if (inputCaptcha === "blackout") {
addUserData({ role: "artist" });
addRoleSpecificData({ condition: ArtistCondition.TOTAL_ACCESS });
let artistPoem: Poem = {
passageId: "",
text: [],
sparkConversation: [],
writeConversation: [],
sparkNotes: "",
writeNotes: "",
};
artistPoem.sparkConversation = [];
artistPoem.sparkNotes = "";
addRoleSpecificData({
poem: artistPoem,
});
navigate("/artist/blackout");
} else {
toaster.create({
description: "Captcha does not match! Try again.",
Expand Down
19 changes: 14 additions & 5 deletions client/src/pages/artist/step2/Step2.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { useNavigate } from "react-router-dom";
import { useState, useRef, useCallback, useEffect } from "react";
import { useState, useRef, useCallback, useEffect, useContext } from "react";
import MultiPageTemplate from "../../../components/shared/pages/multiPage";
import BlackoutPoetry from "../../../components/blackout/Blackout";
import type { Artist, ArtistCondition, Message } from "../../../types";
import { useContext } from "react";
import type {
Artist,
ArtistCondition,
Message,
PoemSnapshot,
} from "../../../types";
import { DataContext } from "../../../App";
import { Stage } from "../../../types";

Expand All @@ -21,6 +25,7 @@ const ArtistStep2 = () => {

const writeMessagesRef = useRef<Message[]>([]);
const selectedWordIndexesRef = useRef<number[]>([]);
const poemSnapshotsRef = useRef<PoemSnapshot[]>([]);
const writeNotesRef = useRef<string>("");

const [writeNotes, setWriteNotes] = useState(
Expand All @@ -30,11 +35,12 @@ const ArtistStep2 = () => {
artistPoem.sparkConversation || []
);
const [selectedWordIndexes, setSelectedWordIndexes] = useState<number[]>([]);
const [poemSnapshots, setPoemSnapshots] = useState<PoemSnapshot[]>([]);
const userType = userData?.data.condition as ArtistCondition;

const onComplete = useCallback(() => {
artistPoem.writeConversation = writeMessagesRef.current || [];
artistPoem.text = selectedWordIndexesRef.current.sort((a, b) => a - b); // sorts indexes in ascending order
artistPoem.text = selectedWordIndexesRef.current;
artistPoem.writeNotes = writeNotesRef.current || "";

addRoleSpecificData({
Expand All @@ -48,7 +54,8 @@ const ArtistStep2 = () => {
writeMessagesRef.current = writeMessages;
selectedWordIndexesRef.current = selectedWordIndexes;
writeNotesRef.current = writeNotes;
}, [writeMessages, writeNotes, selectedWordIndexes]);
poemSnapshotsRef.current = poemSnapshots;
}, [writeMessages, writeNotes, selectedWordIndexes, poemSnapshots]);

return (
<MultiPageTemplate
Expand All @@ -60,12 +67,14 @@ const ArtistStep2 = () => {
setMessages={setWriteMessages}
notes={writeNotes}
setNotes={setWriteNotes}
selectedWordIndexes={selectedWordIndexes}
>
<div className="h-max w-full flex flex-col justify-between">
<BlackoutPoetry
onSubmit={onComplete}
selectedWordIndexes={selectedWordIndexes}
setSelectedWordIndexes={setSelectedWordIndexes}
setPoemSnapshots={setPoemSnapshots}
/>
</div>
</MultiPageTemplate>
Expand Down
2 changes: 2 additions & 0 deletions client/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,5 @@ export interface SurveyQuestion {
options?: string[]; // For multiple choice
scale?: number; // For scale questions (e.g., 7-point scale)
}

export type PoemSnapshot = { indexes: number[]; timestamp: Date };
Loading