diff --git a/front-end/components/ChatBox.js b/front-end/components/ChatBox.js index 3b26c64..d9687c0 100644 --- a/front-end/components/ChatBox.js +++ b/front-end/components/ChatBox.js @@ -1,21 +1,26 @@ import { useState } from "react"; +import { useTimelineContext } from "@/context/TimelineContext"; export default function ChatBox() { const [messages, setMessages] = useState([]); const [input, setInput] = useState(""); - + const { timelineResult } = useTimelineContext(); const sendMessage = async (e) => { e.preventDefault(); if (!input.trim()) return; const userMessage = { sender: "user", text: input }; setMessages([...messages, userMessage]); - + const [username, tag] = timelineResult.player_id.split("#"); // Example: send to backend/chatbot API - const response = await fetch("/api/chat", { + const response = await fetch("https://v4ft9564pb.execute-api.us-west-2.amazonaws.com/player/ask", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ message: input }), + body: JSON.stringify({ + game_name: username, + tagline: tag, + question: input + }), }); const data = await response.json(); diff --git a/front-end/components/FlipBook.jsx b/front-end/components/FlipBook.jsx index 308a916..6a5b0e4 100644 --- a/front-end/components/FlipBook.jsx +++ b/front-end/components/FlipBook.jsx @@ -7,6 +7,7 @@ import SearchAndCompare from "./SearchandCompare"; import MatchSelector from "./MatchSelector"; import MatchTimeline from "./MatchTimeline"; import { useTimelineContext } from "@/context/TimelineContext"; +import { useRealTimelineContext } from "@/context/RealTimelineContext"; import ChatInput from "./ChatInput"; import ChatOutput from "./ChatOutput.jsx"; import AncientRunicPage from "./AncientRunicPage.jsx"; @@ -22,21 +23,14 @@ const FlipBook = () => { const [onLastPage, setOnLastPage] = useState(false); const [isTurning, setIsTurning] = useState(false); const { timelineResult } = useTimelineContext(); + const { realTimelineResult, setRealTimelineResult} = useRealTimelineContext(); // Match Timeline state + Match Selector const [matches, setMatches] = useState([]); const [selectedMatchId, setSelectedMatchId] = useState(null); // Player stats state - const [player1Stats, setPlayer1Stats] = useState({ - "avg_kda": 0, - "avg_cs_per_min": 0, - "avg_kill_participation": 0, - "avg_dpm": 0, - "avg_gpm": 0, - "avg_solo_kills": 0, - "avg_vision_score": 0, - "avg_cc_time": 0}); + const [player1Stats, setPlayer1Stats] = useState(null); const [player2Stats, setPlayer2Stats] = useState({ "avg_kda": 0, @@ -47,7 +41,7 @@ const FlipBook = () => { "avg_solo_kills": 0, "avg_vision_score": 0, "avg_cc_time": 0}); - + const [mostPlayed, setMostPlayed] = useState(null); // Chat state const [chatMessages, setChatMessages] = useState([]); const [isLoadingChat, setIsLoadingChat] = useState(false); @@ -57,22 +51,77 @@ const FlipBook = () => { }, []); const [searchQuery, setSearchQuery] = useState(""); + async function pollUntilReady(interval = 5000, timeout = 60000) { + const start = Date.now(); + while (true) { + if(!timelineResult) continue; + const [username, tag] = timelineResult.player_id.split("#"); + try { + const response = await fetch(`https://v4ft9564pb.execute-api.us-west-2.amazonaws.com/player/profile?game_name=${username}&tagline=${tag}`); + if (response.ok) { + const data = await response.json(); + return data; + } + } catch (err) { + console.warn("Polling error:", err.message); + } + + if (Date.now() - start > timeout) { + throw new Error("Polling timed out"); + } + + await new Promise(resolve => setTimeout(resolve, interval)); + } + } + + useEffect(() => { + let isActive = true; + async function fetchRealTimelineResult() { + try { + console.log("Polling for timeline result..."); + const data = await pollUntilReady( + 5000, + 600000 + ); + + if (isActive) { + console.log("Received 200 response:", data); + setRealTimelineResult(data); + } + } catch (err) { + console.error("Polling failed:", err); + } + } + + fetchRealTimelineResult(); + + return () => { + isActive = false; + }; + }, []); const pageRefs = useRef([]); const isInitialized = useRef(false); useEffect(() => { - if (!timelineResult) return; + + + if (!timelineResult) return; + setPlayer1Stats(timelineResult.stats) + const mostPlayedList = timelineResult.most_played_champions + const championsArray = Object.entries(mostPlayedList).map(([name, games]) => ({ name, games })); + setMostPlayed(championsArray); + + if (!realTimelineResult) return; - if (timelineResult.timeline_data) { + if (realTimelineResult.timeline_data) { - setMatches(timelineResult.timeline_data); - setSelectedMatchId(timelineResult.timeline_data[0]?.match_id || null); + setMatches(realTimelineResult.timeline_data); + setSelectedMatchId(realTimelineResult.timeline_data[0]?.match_id || null); } else { - console.warn("No timeline data found in search result:", timelineResult); + console.warn("No timeline data found in search result:", realTimelineResult); } - setPlayer1Stats(timelineResult.stats) - }, [timelineResult]); + }, [timelineResult, realTimelineResult]); // Get the currently selected match @@ -103,19 +152,23 @@ const FlipBook = () => { setIsLoadingChat(true); try { - // TODO: Replace with actual API call to your backend - const response = await fetch("/api/chat", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ message: userMessage }), - }); + const [username, tag] = timelineResult.player_id.split("#"); + const response = await fetch("https://v4ft9564pb.execute-api.us-west-2.amazonaws.com/player/ask", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + game_name: username, + tagline: tag, + question: userMessage + }), + }); const data = await response.json(); // Add bot response const botMessage = { sender: "bot", - text: data.reply || "I received your question. Let me analyze that for you...", + text: data.answer || "I received your question. Let me analyze that for you...", timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' @@ -140,9 +193,10 @@ const FlipBook = () => { }, []); // Create page structure once and store it in a ref - const pageStructure = useMemo(() => + const pageStructure = useMemo(() => { + if (!mostPlayed || !timelineResult || !player1Stats) return []; - [ + return [ { cover: "book_cover.jpg", frontCover: true, id: 0 }, { front: { runeCount={10} // Number of runes (default 9) />, back: , id: 2 }, @@ -285,20 +337,17 @@ const FlipBook = () => { id: 11 }, { cover: "green-cover.jpg", id: 12 }, - ], []); + ]}, [timelineResult, mostPlayed, player1Stats]); // Initialize pages only once useEffect(() => { - if (isInitialized.current) return; - + if (!pageStructure.length) return; + const total = pageStructure.length; setPages(pageStructure); setZIndices(Array.from({ length: total }, (_, i) => total - i + 1)); setFlippedStates(Array(total).fill(false)); - - pageRefs.current = Array(total) - .fill() - .map(() => React.createRef()); + pageRefs.current = Array(total).fill().map(() => React.createRef()); isInitialized.current = true; }, [pageStructure]); diff --git a/front-end/components/SearchandCompare.js b/front-end/components/SearchandCompare.js index 24ca0cb..73cf063 100644 --- a/front-end/components/SearchandCompare.js +++ b/front-end/components/SearchandCompare.js @@ -13,7 +13,7 @@ const SearchAndCompare = ({ player1Stats, onPlayer2Found }) => { "avg_vision_score": 0, "avg_cc_time": 0}); const [hasSearched, setHasSearched] = useState(false); // Track if user has searched - const { setFriendResult } = useFriendContext(); + const { friendResult, setFriendResult } = useFriendContext(); const stats = ["avg_kda", "avg_cs_per_min", "avg_kill_participation", "avg_dpm", "avg_gpm", "avg_solo_kills", "avg_vision_score", "avg_cc_time"]; const displayStats = { "avg_kda": "KDA", @@ -116,7 +116,8 @@ const SearchAndCompare = ({ player1Stats, onPlayer2Found }) => { {/* Stats Display - Identical to Social */}

- Searched Player's Name + {!friendResult && "Search for a player"} + {friendResult && `${friendResult.player_id}`}

diff --git a/front-end/components/Social.jsx b/front-end/components/Social.jsx index 90d01e3..ec3b86b 100644 --- a/front-end/components/Social.jsx +++ b/front-end/components/Social.jsx @@ -1,8 +1,10 @@ import React from "react"; +import { useTimelineContext } from "@/context/TimelineContext"; const Social = ({ input1 = {}, input2 = {} }) => { const stats1 = input1; const stats2 = input2; + const { timelineResult } = useTimelineContext(); const getStatColor = (stat1, stat2) => { const val1 = stat1; @@ -36,7 +38,7 @@ const Social = ({ input1 = {}, input2 = {} }) => { {/* Stats Display */}

- Player Name + {timelineResult.player_id}

diff --git a/front-end/components/SummaryBack.jsx b/front-end/components/SummaryBack.jsx index 561ad8e..0e80f4a 100644 --- a/front-end/components/SummaryBack.jsx +++ b/front-end/components/SummaryBack.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect, useRef } from "react"; import TraitPopup from "./TraitPopup"; import Image from "next/image"; +import { regions } from "@/data/regions"; const SummaryBack = ({ data }) => { const [activeTrait, setActiveTrait] = useState(null); @@ -15,21 +16,7 @@ const SummaryBack = ({ data }) => { "Empire-Building": "Focuses on expansion and strategic dominance.", }; - const Regions = { - //"Bilgewater" : `Citizens from Bilgewater have a high affinity for gold and are prone to make risky, daring plays on their lonesome. They value efficient gold generation per minute and are more willing to take tower dives if they think it can swing the tides in their favor. Based on your stats, you make an average of ${gpm} gold per minute. You’ve also gotten roughly ${avg_solo_kills} solo kills per game as well as an average of ${avg_kills_near_tower} kills near enemy tower. These impressive stats prove that you are a bonafide Bilgerat, ready to plunder the enemy team’s economy.`, - //"Noxus" : `Noxians are known for their bloodlust and are eager to show off their strength to any unfortunate opponents that happen to stand in their way. Not only do they live for the thrill of battle, but they also take great pleasure in asserting their dominance as quickly and brutally as possible. According to your average damage per minute, ${dpm}, as well as your exemplary average early gold advantage, ${ega}, you are a perfect fit for the Noxian archetype.`, - //"Bandle_City" : `Everyone in Bandle City knows that the scout’s code is one of the most important rulebooks to follow for any aspiring Bandle scout. Bandle scouts are known for their vigilance and their dedication to never be detected. The average Bandle scout never backs down from a fight and always comes prepared for anything. Scouts usually have a high vision score, high KDA and can always find a way to outplay when outnumbered. Your average KDA, ${avg_kda}, and vision score, ${vs}, are exceptionally high. Your average kills when outnumbered, ${avg_outnumbered_kills}, are exceptionally high which demonstrates that you are ready to become a Bandle scout.`, - //"Demacia" : `Long ago, many Demacian soldiers believed that as long as they stood together, firm in their beliefs, they would never capitulate to the enemy. This same belief still holds true today, as the Demacian empire still stands tall, firm in their belief that what they do is right. Demacians are known for working together to destroy their enemies while making sure to keep their allies safe. Your average kill participation, ${kp}, and your teamfight damage, ${tfdmg}, are exceptionally high, but your average shielding on allies, ${soa}, proves that you know your teammates come first.`, - //"Ionia" : `When Noxus invaded the first lands, everything changed for the people of Ionia. Families were split apart, temples were destroyed, and peace was nowhere to be found. The scars from Noxus linger on Ionia’s once peaceful lands, and now Ionians are ready for anything. To be an Ionian, you must be sharp and quick-witted if you want to stay alive. Ionians typically have exceptional cs and kill participation while also maintaining a high KDA. They are also known to be one with the land around them, meaning that they on average achieve a stellar vision score. Your KDA, {kda}, as well as your kill participation ${kp}, cs ${cs} and vision score ${vs}, prove that you are an honorary Ionian native.`, - //"Ixtal" : `In the jungles of Ixtal, the hunt is what is considered to be the most sacred tradition held by the natives. The hunt brings in food, pays for shelter, and can save lives. Hunting the monsters in Ixtal can provide several benefits, such as honing your skills, immense amounts of meat, and special boons. A good jungler translates very easily into being an excellent hunter. Getting a high amount of dragon and herald kills per game means that you are a valuable asset to your team’s probability of success. Your high objective damage, ${objdmg}, paired with high dragon and herald kills, ${dkills}, ${hkills}, exhibits how hard of a jungle carry you can be.`, - //"Piltover" : `Piltover prides itself on its constant need for innovation, always improving upon each iteration to produce wondrous results. There’s always a hidden cost that’s required to continue improving, which is why every up-and-coming inventor needs a sponsor or a wealthy background. In order to keep your place as an honorary Piltovian, your gold per minute must be high enough to satisfy the needs of your research and production costs. Since your cs per minute, ${cs}, and your cs consistency, ${cs_c}, are always exceptionally high, your gold per minute, ${gpm}, goes beyond the average Piltovian salary. The city of progress can make several technological advancements thanks to your immense wealth and consistent profits.`, - //"Shadow_Isles" : `The Blessed Isles were once a place of refuge where people could go experience tranquility and safety while having the luxury of healing their wounds by taking a dip in the sacred waters. Everything changed, however, when a magical calamity befell the isles, turning them into the Shadow Isles. The isles that were once known for harboring life and prosperity now only hold death and despair for those who enter. However, not all has been lost, for there are those that reside in the Shadow Isles that want to restore them to their former glory. To be able to become a part of the few who can survive the Shadow Isles, an exceptional mastery of healing those around you accompanied by a will to stay alive is required. Your average lifespan per game, ${life}, outlasts even the safest of players, while your healing, ${heals}, is unmatched. You definitely have what it takes to return the Shadow Isles to their former glory.`, - "Shurima": `To most, Shurima seems like a harsh desert wasteland with nothing of value left in it after its once great empire fell. For those who are patient and are willing to look beneath the sand, Shurima harbors an indescribable amount of wealth and power. This power to become ascended can only be tapped into by a certain few who prove themselves to be worthy after a substantial amount of time. Based on your high average cs per game, {cs}, and your exceptional gold generation per minute, {gpm}, your playstyle makes you the perfect candidate to become a Shuriman ascended.`, - //"Targon" : `Anyone who scaled Mount Targon knows that the journey is treacherous and filled with adversity, but those who reach the top have the chance to be touched by celestial beings imbuing them with unimaginable power. To climb this mountain alone, however, is a death sentence; this climb encourages people to seek out unlikely allies to forge strong bonds that can soldier through the mountain's harsh conditions. Teamwork alone isn’t the only thing that’s needed; a summoner’s individual support skills like warding, healing, and shielding are necessary for the uncertain path ahead. Your average vision score per game, ${v_score}, demonstrates a perceptive and cautious player. Your average healing and shielding, ${heals}, ${shields}, on teammates is massive. This all but seals the deal that you are more than capable of making it to the top of Mount Targon.`, - //"Freljord" : `The Freljord is a combination of harsh mountain ranges and cold, bitter wind that can rattle the bones of even the toughest of Runeterrans. Iceborn, the special few that are native to this land, have adapted to these tough conditions and have managed to thrive in this icy area. Iceborn have retained skills such as having insanely long crowd control chains while being an unscalable wall to anyone who dares challenge them. Your stats show that you apply an exceptionally long amount of crowd control, ${cc}, to your enemies. You also have an exceptional will to survive which is shown through how long you’ve survived, ${time_alive}, during each game. You are a true Iceborn.`, - //"Void" : `The Void. A pit that houses a variety of unspeakable horrors from beyond Runeterra that are hungry to consume anything that lives. Almost nothing survives once they enter the Void, the only exception being the Voidborne. All of the Voidborne deal insane amounts of damage, obliterating anything weaker than them in their path, which allows them to survive the harsh conditions of the Void. A high average damage per minute accompanied with a high amount of solo kills and teamfight damage. Your high average damage per minute, ${dpm}, identifies you as a fearsome enemy that can tear through the enemy frontline. Your teamfight damage, ${tfd}, and your solo kills, ${sk}, per game prove that you are an unstoppable force alone and with your team.`, - //"Zaun" : `The underbelly of Piltover, Zaun, is a place where dreams of progress go to die and a quiet desperation to survive replaces it. The streets of Zaun make it difficult to traverse if you aren’t already a resilient cutthroat. There’s plenty of opportunities to be kidnapped, mugged or straight up killed in cold blood. The good people of Zaun have adapted to this lifestyle, putting their life on the line in order to eliminate as many of their enemies as possible. Zaunites typically have a high number of deaths but manage to take down at least one or more enemy players with them. Your average deaths, ${death_con}, are quite high, however, you manage to take down around ${avg_outnumbered_kills} champions before you fall. The average amount of assassinations you perform on enemy champions are roughly ${avg_pick_kills} which means your map awareness is exemplary.` - }; + useEffect(() => { const handleClickOutside = () => { @@ -53,7 +40,7 @@ const SummaryBack = ({ data }) => { return (
-

Username

+

{data.username}

{/* Region info */}
@@ -69,7 +56,7 @@ const SummaryBack = ({ data }) => { height={32} /> -

{Regions[data.region]}

+

{regions[data.region.toLowerCase()].description(data.playerStats)}

{/* Profile traits with popups */} @@ -105,10 +92,10 @@ const SummaryBack = ({ data }) => {

Key Statistics

    -
  • Games Played: {data.statistics.gamesPlayed}
  • Win Rate: {data.statistics.winRate}
  • Average KDA: {data.statistics.averageKDA}
  • CS/M: {data.statistics.cspm}
  • +
  • Gold/M: {data.statistics.goldpm}
{/* Most Played Champions */} diff --git a/front-end/context/RealTimelineContext.js b/front-end/context/RealTimelineContext.js new file mode 100644 index 0000000..f583b29 --- /dev/null +++ b/front-end/context/RealTimelineContext.js @@ -0,0 +1,15 @@ +"use client"; +import { createContext, useContext, useState } from "react"; + +const RealTimelineContext = createContext(); + +export function RealTimelineContextProvider({ children }) { + const [realTimelineResult, setRealTimelineResult] = useState(null); + return ( + + {children} + + ); +} + +export const useRealTimelineContext = () => useContext(RealTimelineContext); diff --git a/front-end/data/regions.js b/front-end/data/regions.js new file mode 100644 index 0000000..9e2f17b --- /dev/null +++ b/front-end/data/regions.js @@ -0,0 +1,54 @@ +export const regions = { + "bilgewater" : { + icon: "/images/regions/bilgewater_crest_icon.png", + description: (stats) => `Citizens from Bilgewater have a high affinity for gold and are prone to make risky, daring plays on their lonesome. They value efficient gold generation per minute and are more willing to take tower dives if they think it can swing the tides in their favor. Based on your stats, you make an average of ${stats.avg_gpm.toFixed(2)} gold per minute. You’ve also gotten roughly ${stats.avg_solo_kills.toFixed(2)} solo kills per game as well as an average of ${stats.avg_kills_near_tower.toFixed(2)} kills near enemy tower. These impressive stats prove that you are a bonafide Bilgerat, ready to plunder the enemy team’s economy.`, + }, + "noxus": { + icon: "/images/regions/noxus_crest_icon.png", + description: (stats) => `Noxians are known for their bloodlust and are eager to show off their strength to any unfortunate opponents that happen to stand in their way. Not only do they live for the thrill of battle, but they also take great pleasure in asserting their dominance as quickly and brutally as possible. According to your average damage per minute, ${stats.avg_dpm.toFixed(2)}, as well as your exemplary average early gold advantage, ${stats.avg_early_gold_adv.toFixed(2)}, you are a perfect fit for the Noxian archetype.`, + }, + "bandle": { + icon: "/images/regions/bandle_city_crest_icon.png", + description: (stats) => `Everyone in Bandle City knows that the scout’s code is one of the most important rulebooks to follow for any aspiring Bandle scout. Bandle scouts are known for their vigilance and their dedication to never be detected. The average Bandle scout never backs down from a fight and always comes prepared for anything. Scouts usually have a high vision score, high KDA and can always find a way to outplay when outnumbered. Your average KDA, ${stats.avg_kda.toFixed(2)}, and vision score, ${stats.avg_vision_score.toFixed(2)}, are exceptionally high. Your average kills when outnumbered, ${stats.avg_outnumbered_kills.toFixed(2)}, are exceptionally high which demonstrates that you are ready to become a Bandle scout.`, + }, + "demacia": { + icon: "/images/regions/demacia_crest_icon.png", + description: (stats) => `Long ago, many Demacian soldiers believed that as long as they stood together, firm in their beliefs, they would never capitulate to the enemy. This same belief still holds true today, as the Demacian empire still stands tall, firm in their belief that what they do is right. Demacians are known for working together to destroy their enemies while making sure to keep their allies safe. Your average kill participation, ${stats.avg_kill_participation.toFixed(2)}, and your teamfight damage, ${stats.avg_team_damage_pct.toFixed(2)}, are exceptionally high, but your average shielding on allies, ${stats.avg_shields_on_teammates.toFixed(2)}, proves that you know your teammates come first.`, + }, + "ionia": { + icon: "/images/regions/ionia_crest_icon.png", + description: (stats) => `When Noxus invaded the first lands, everything changed for the people of Ionia. Families were split apart, temples were destroyed, and peace was nowhere to be found. The scars from Noxus linger on Ionia’s once peaceful lands, and now Ionians are ready for anything. To be an Ionian, you must be sharp and quick-witted if you want to stay alive. Ionians typically have exceptional cs and kill participation while also maintaining a high KDA. They are also known to be one with the land around them, meaning that they on average achieve a stellar vision score. Your KDA, ${stats.avg_kda.toFixed(2)}, as well as your kill participation ${stats.avg_kill_participation.toFixed(2)}, cs ${stats.avg_cs_per_min.toFixed(2)} and vision score ${stats.avg_vision_score.toFixed(2)}, prove that you are an honorary Ionian native.`, + }, + "ixtal": { + icon: "/images/regions/ixtal_crest_icon.png", + description: (stats) => `In the jungles of Ixtal, the hunt is what is considered to be the most sacred tradition held by the natives. The hunt brings in food, pays for shelter, and can save lives. Hunting the monsters in Ixtal can provide several benefits, such as honing your skills, immense amounts of meat, and special boons. A good jungler translates very easily into being an excellent hunter. Getting a high amount of dragon and herald kills per game means that you are a valuable asset to your team’s probability of success. Your high objective damage, ${stats.avg_objective_damage.toFixed(2)}, paired with high dragon and herald kills, ${stats.avg_dragon_takedowns.toFixed(2)}, ${stats.avg_herald_takedowns.toFixed(2)}, exhibits how hard of a jungle carry you can be.`, + }, + "piltover": { + icon: "/images/regions/piltover_crest_icon.png", + description: (stats) => `Piltover prides itself on its constant need for innovation, always improving upon each iteration to produce wondrous results. There’s always a hidden cost that’s required to continue improving, which is why every up-and-coming inventor needs a sponsor or a wealthy background. In order to keep your place as an honorary Piltovian, your gold per minute must be high enough to satisfy the needs of your research and production costs. Since your cs per minute, ${stats.avg_cs_per_min.toFixed(2)}, and your cs consistency, ${stats.cs_consistency.toFixed(2)}, are always exceptionally high, your gold per minute, ${stats.avg_gpm.toFixed(2)}, goes beyond the average Piltovian salary. The city of progress can make several technological advancements thanks to your immense wealth and consistent profits.` + }, + "shadow_isles": { + icon: "/images/regions/shadow_isles_crest_icon.png", + description: (stats) => `The Blessed Isles were once a place of refuge where people could go experience tranquility and safety while having the luxury of healing their wounds by taking a dip in the sacred waters. Everything changed, however, when a magical calamity befell the isles, turning them into the Shadow Isles. The isles that were once known for harboring life and prosperity now only hold death and despair for those who enter. However, not all has been lost, for there are those that reside in the Shadow Isles that want to restore them to their former glory. To be able to become a part of the few who can survive the Shadow Isles, an exceptional mastery of healing those around you accompanied by a will to stay alive is required. Your average lifespan per game, ${stats.avg_longest_alive.toFixed(2)}, outlasts even the safest of players, while your healing, ${stats.avg_heals_on_teammates.toFixed(2)}, is unmatched. You definitely have what it takes to return the Shadow Isles to their former glory.`, + }, + "shurima": { + icon: "/images/regions/shurima_crest_icon.png", + description: (stats) => `To most, Shurima seems like a harsh desert wasteland with nothing of value left in it after its once great empire fell. For those who are patient and are willing to look beneath the sand, Shurima harbors an indescribable amount of wealth and power. This power to become ascended can only be tapped into by a certain few who prove themselves to be worthy after a substantial amount of time. Based on your high average cs per game, ${stats.avg_cs_per_min.toFixed(2)}, and your exceptional gold generation per minute, ${stats.avg_gpm.toFixed(2)}, your playstyle makes you the perfect candidate to become a Shuriman ascended.` + }, + "targon": { + icon: "/images/regions/mt_targon_crest_icon.png", + description: (stats) => `Anyone who’s scaled Mount Targon knows that the journey is treacherous and filled with adversity, but those who reach the top have the chance to be touched by celestial beings imbuing them with unimaginable power. To climb this mountain alone, however, is a death sentence; this climb encourages people to seek out unlikely allies to forge strong bonds that can soldier through the mountain's harsh conditions. Teamwork alone isn’t the only thing that’s needed; a summoner’s individual support skills like warding, healing, and shielding are necessary for the uncertain path ahead. Your average vision score per game, ${stats.avg_vision_score.toFixed(2)}, demonstrates a perceptive and cautious player. Your average healing and shielding, ${stats.avg_heals_on_teammates.toFixed(2)}, ${stats.avg_shields_on_teammates.toFixed(2)}, on teammates is massive. This all but seals the deal that you are more than capable of making it to the top of Mount Targon.`, + }, + "freljord": { + icon: "/images/regions/freljord_crest_icon.png", + description: (stats) => `The Freljord is a combination of harsh mountain ranges and cold, bitter wind that can rattle the bones of even the toughest of Runeterrans. Iceborn, the special few that are native to this land, have adapted to these tough conditions and have managed to thrive in this icy area. Iceborn have retained skills such as having insanely long crowd control chains while being an unscalable wall to anyone who dares challenge them. Your stats show that you apply an exceptionally long amount of crowd control, ${stats.avg_cc_time.toFixed(2)}, to your enemies. You also have an exceptional will to survive which is shown through how long you’ve survived, ${stats.death_consistency.toFixed(2)}, during each game. You are a true Iceborn.`, + }, + "void": { + icon: "/images/regions/void_crest_icon.png", + description: (stats) => `The Void. A pit that houses a variety of unspeakable horrors from beyond Runeterra that are hungry to consume anything that lives. Almost nothing survives once they enter the Void, the only exception being the Voidborne. All of the Voidborne deal insane amounts of damage, obliterating anything weaker than them in their path, which allows them to survive the harsh conditions of the Void. A high average damage per minute accompanied with a high amount of solo kills and teamfight damage. Your high average damage per minute, ${stats.avg_dpm.toFixed(2)}, identifies you as a fearsome enemy that can tear through the enemy frontline. Your teamfight damage, ${stats.avg_team_damage_pct.toFixed(2)}, and your solo kills, ${stats.avg_solo_kills.toFixed(2)}, per game prove that you are an unstoppable force alone and with your team`, + }, + "zaun": { + icon: "/images/regions/zaun_crest_icon.png", + description: (stats) => `The underbelly of Piltover, Zaun, is a place where dreams of progress go to die and a quiet desperation to survive replaces it. The streets of Zaun make it difficult to traverse if you aren’t already a resilient cutthroat. There’s plenty of opportunities to be kidnapped, mugged or straight up killed in cold blood. The good people of Zaun have adapted to this lifestyle, putting their life on the line in order to eliminate as many of their enemies as possible. Zaunites typically have a high number of deaths but manage to take down at least one or more enemy players with them. Your average deaths, ${stats.death_consistency.toFixed(2)}, are quite high, however, you manage to take down around ${stats.avg_outnumbered_kills.toFixed(2)} champions before you fall. The average amount of assassinations you perform on enemy champions are roughly ${stats.avg_pick_kills.toFixed(2)} which means your map awareness is exemplary.`, + } +} \ No newline at end of file diff --git a/front-end/pages/_app.js b/front-end/pages/_app.js index 966f56f..f4897a1 100644 --- a/front-end/pages/_app.js +++ b/front-end/pages/_app.js @@ -9,6 +9,7 @@ import "@/styles/FlipPage.css"; import "@/styles/Summary.css"; import { TimelineContextProvider } from "@/context/TimelineContext"; import { FriendContextProvider } from "@/context/FriendContext"; +import { RealTimelineContextProvider } from "@/context/RealTimelineContext"; import "@/styles/detentionslip.css"; import "@/styles/index.css"; @@ -16,11 +17,14 @@ export default function App({ Component, pageProps }) { return ( <>
- + + - + + +
); diff --git a/front-end/pages/index.js b/front-end/pages/index.js index a45a1de..aad3484 100644 --- a/front-end/pages/index.js +++ b/front-end/pages/index.js @@ -7,19 +7,25 @@ export default function Home() { const [taglineValue, setTaglineValue] = useState(""); const [gameCountValue, setCountValue] = useState(10); - const handleChange = (event) => { - setInputValue(event.target.value); + const handleUsernameChange = (event) => { + setUsernameValue(event.target.value); + }; + const handleTaglineChange = (event) => { + setTaglineValue(event.target.value); + }; + const handleCountChange = (event) => { + setCountValue(event.target.value); }; const { setTimelineResult } = useTimelineContext(); const router = useRouter(); const handleSearch = async () => { - router.push("/FlipBook"); + router.push("/loading"); const endpoint = "https://v4ft9564pb.execute-api.us-west-2.amazonaws.com/player/process"; const body = { - game_name: "ShadowLeaf", - tagline: "8005", - num_games: 1 + game_name: usernameValue, + tagline: taglineValue, + num_games: gameCountValue }; try { @@ -39,11 +45,12 @@ export default function Home() { const timelineData = await res.json(); setTimelineResult(timelineData); + router.push("/FlipBook") } catch (err) { console.error("Error fetching API data:", err); setTimelineResult({ error: "Failed to load timeline." }); - router.push("/") + router.push("/invalid") } }; @@ -54,9 +61,9 @@ export default function Home() { {/* Content */}
- - - + + +
); diff --git a/package.json b/package.json deleted file mode 100644 index 0b1f9c8..0000000 --- a/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "riot_api", - "version": "1.0.0", - "description": "project for Riot x AWS Rift Rewind hackathon", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/syliem1/Rift_Rewind.git" - }, - "keywords": [], - "author": "", - "license": "ISC", - "type": "commonjs", - "bugs": { - "url": "https://github.com/syliem1/Rift_Rewind/issues" - }, - "homepage": "https://github.com/syliem1/Rift_Rewind#readme" -}