Mistral-AI-Game-Jam/DefendDaniel2
7
1// /$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$$$ /$$ /$$ /$$$$$$$$ /$$$$$$ /$$$$$ /$$$$$$ /$$$$$$$ 2// /$$__ $$|_ $$_/| $$ | $$| $$_____/ | $$$ /$$$| $$_____/ /$$__ $$ |__ $$ /$$__ $$| $$__ $$3// | $$ \__/ | $$ | $$ | $$| $$ | $$$$ /$$$$| $$ | $$ \ $$ | $$| $$ \ $$| $$ \ $$4// | $$ /$$$$ | $$ | $$ / $$/| $$$$$ | $$ $$/$$ $$| $$$$$ | $$$$$$$$ | $$| $$ | $$| $$$$$$$ 5// | $$|_ $$ | $$ \ $$ $$/ | $$__/ | $$ $$$| $$| $$__/ | $$__ $$ /$$ | $$| $$ | $$| $$__ $$6// | $$ \ $$ | $$ \ $$$/ | $$ | $$\ $ | $$| $$ | $$ | $$ | $$ | $$| $$ | $$| $$ \ $$7// | $$$$$$/ /$$$$$$ \ $/ | $$$$$$$$ | $$ \/ | $$| $$$$$$$$ | $$ | $$ | $$$$$$/| $$$$$$/| $$$$$$$/8// \______/ |______/ \_/ |________/ |__/ |__/|________/ |__/ |__/ \______/ \______/ |_______/ 9//10// Hi, I'm Roland and i'm looking for a job.11// Resume in /public/resume.pdf12// roland.vrignon@roland.com13// https://www.linkedin.com/in/roland-vrignon/14//15 16'use client';17 18import { useState, useEffect } from 'react';19import MenuScene from '../components/menu/Menu';20import IntroScene from '../components/intro/Intro';21import CourtScene from '../components/court/Court';22import DefenseScene from '../components/defense/Defense';23import LawyerScene from '../components/lawyer/Lawyer';24import EndScene from '../components/end/End';25import AccusationScene from '../components/accusation/Accusation';26 27// Types pour notre état28type Language = 'fr' | 'en' | 'es';29 30type Scene = 'menu' | 'intro' | 'accusation' | 'court' | 'defense' | 'lawyer' | 'end';31interface Story {32 accusation: {33 description: string;34 alibi: string[];35 };36}37 38interface Message {39 content: string;40 role: 'lawyer' | 'judge';41 requiredWords?: string[];42}43 44interface Chat {45 messages: Message[];46}47 48interface Verdict {49 verdict: boolean;50 argument: string;51 prisonYears: number;52}53 54const intro = {55 fr: {56 title: "L'Avocat de l'IA",57 description: `Daniel est un mec banale. Il n'a rien fait de mal.\nPourtant, il est convoqué aujourd'hui dans ce tribunal. Pauvre Daniel...`,58 start: "Commencer"59 },60 en: {61 title: "The AI Lawyer", 62 description: `Daniel is an ordinary guy. He hasn't done anything wrong.\nYet he's been summoned to court today. Poor Daniel...`,63 start: "Start"64 },65 es: {66 title: "El Abogado de la IA",67 description: `Daniel es un tipo corriente. No ha hecho nada malo.\nSin embargo, ha sido convocado a la corte hoy. Pobre Daniel...`,68 start: "Empezar"69 }70}71 72const sceneOrder: Scene[] = ['menu', 'intro', 'accusation', 'court', 'defense', 'lawyer'];73 74export default function Home() {75 // Gestion des scènes76 const [currentScene, setCurrentScene] = useState<Scene>('menu');77 const [story, setStory] = useState<Story | null>(null);78 const [chat, setChat] = useState<Chat>({ messages: [] });79 // États principaux du jeu80 const [language, setLanguage] = useState<Language>('fr');81 82 const [round, setRound] = useState<number>(1);83 84 const [requiredWords, setRequiredWords] = useState<string[]>([])85 86 const [currentQuestion, setCurrentQuestion] = useState<string>('');87 88 const [reaction, setReaction] = useState<string>('');89 90 91 const [verdict, setVerdict] = useState<Verdict | null>(null);92 const resetGame = () => {93 setCurrentScene('menu');94 setStory(null);95 setChat({ messages: [] });96 setLanguage('fr');97 setRound(1);98 setRequiredWords([]);99 };100 101 const setNextScene = async () => {102 if (currentScene === 'lawyer') {103 if (round < 4) {104 setCurrentScene('court');105 } else {106 // Generate judge's verdict before ending107 const generateVerdict = async () => {108 try {109 const response = await fetch('/api/text/verdict', {110 method: 'POST',111 headers: {112 'Content-Type': 'application/json',113 },114 body: JSON.stringify({115 language,116 story,117 chat118 })119 });120 121 const data = await response.json();122 123 if (!data.success) {124 throw new Error('Failed to generate verdict');125 }126 127 setVerdict(data.verdict);128 } catch (error) {129 console.error('Error generating verdict:', error);130 }131 };132 133 await generateVerdict();134 135 setCurrentScene('end');136 }137 return;138 }139 140 if (currentScene === 'end') {141 resetGame();142 return;143 }144 145 const currentIndex = sceneOrder.indexOf(currentScene);146 if (currentIndex !== -1 && currentIndex < sceneOrder.length - 1) {147 setCurrentScene(sceneOrder[currentIndex + 1]);148 }149 };150 151 // Props communs à passer aux composants152 const commonProps = {153 intro,154 language,155 setLanguage,156 round,157 setRound,158 setCurrentScene,159 setNextScene,160 story,161 currentQuestion,162 setCurrentQuestion,163 requiredWords,164 setRequiredWords,165 chat,166 setChat,167 reaction,168 setReaction,169 verdict,170 setVerdict171 };172 173 useEffect(() => {174 const fetchStory = async () => {175 try {176 const response = await fetch('/api/text/story', {177 method: 'POST',178 headers: {179 'Content-Type': 'application/json',180 },181 body: JSON.stringify({ language })182 });183 184 const data = await response.json();185 186 if (data.success && data.story) {187 setStory({188 accusation: {189 description: data.story.description,190 alibi: data.story.alibi,191 }192 });193 }194 } catch (error) {195 console.error('Erreur lors de la récupération de l\'histoire:', error);196 }197 };198 199 200 if (currentScene === 'intro') {201 fetchStory();202 }203 // eslint-disable-next-line react-hooks/exhaustive-deps204 }, [currentScene]); // on écoute les changements de currentScene205 206 useEffect(() => {207 const fetchQuestion = async () => {208 try {209 const response = await fetch('/api/text/question', {210 method: 'POST',211 headers: {212 'Content-Type': 'application/json',213 },214 body: JSON.stringify({215 language,216 story: story?.accusation,217 chat: chat218 })219 });220 221 const data = await response.json();222 if (data.question && data.words) {223 setCurrentQuestion(data.question);224 setRequiredWords(data.words);225 if (data.reaction && data.reaction !== '') {226 setReaction(data.reaction);227 }228 setChat(prevChat => ({229 messages: [...prevChat.messages, { content: data.question, role: 'judge' }]230 }));231 }232 } catch (error) {233 console.error('Erreur lors de la récupération de la question:', error);234 }235 };236 237 if ((currentScene === 'accusation' && story) || (currentScene === 'lawyer' && round < 3 && story)) {238 fetchQuestion();239 }240 // eslint-disable-next-line react-hooks/exhaustive-deps241 }, [currentScene]);242 243 switch (currentScene) {244 case 'menu':245 return <MenuScene {...commonProps} />;246 case 'intro':247 return <IntroScene {...commonProps} />;248 case 'accusation':249 return <AccusationScene {...commonProps} />;250 case 'court':251 return <CourtScene {...commonProps} />;252 case 'defense':253 return <DefenseScene {...commonProps} />;254 case 'lawyer':255 return <LawyerScene {...commonProps} />;256 case 'end':257 return <EndScene {...commonProps} />;258 default:259 return <MenuScene {...commonProps} />;260 }261}