From dbb99eddaeb2e4c8076fe84e937572b4d4033033 Mon Sep 17 00:00:00 2001 From: Logan Davidson Date: Fri, 2 Feb 2024 16:57:34 +0000 Subject: [PATCH 1/2] Add the Initiate Situation action Add the Initiate Situation action, which can be performed by the user in it's correct place in the sequence of play. Also add test coverage. The new action doesn't do anything yet. There isn't even an action log for it. --- backend/rorapp/functions/__init__.py | 1 + .../rorapp/functions/faction_leader_helper.py | 31 +----- .../rorapp/functions/forum_phase_helper.py | 94 ++++++++++++++++++- .../rorapp/functions/forum_phase_starter.py | 29 +++--- backend/rorapp/functions/game_starter.py | 2 +- backend/rorapp/tests/forum_phase_tests.py | 54 +++++++---- backend/rorapp/tests/test_helper.py | 13 ++- backend/rorapp/views/submit_action.py | 18 +++- frontend/components/GamePage.tsx | 5 +- frontend/components/ProgressSection.tsx | 1 + .../actionDialogs/ActionDialog.module.css | 11 --- .../components/actionDialogs/ActionDialog.tsx | 2 + .../ActionDialog_FaceMortality.tsx | 19 ++-- .../ActionDialog_InitiateSituation.tsx | 86 +++++++++++++++++ .../ActionDialog_SelectFactionLeader.tsx | 17 ++-- frontend/data/actions.json | 4 + 16 files changed, 281 insertions(+), 106 deletions(-) delete mode 100644 frontend/components/actionDialogs/ActionDialog.module.css create mode 100644 frontend/components/actionDialogs/ActionDialog_InitiateSituation.tsx diff --git a/backend/rorapp/functions/__init__.py b/backend/rorapp/functions/__init__.py index 7e211078..209a3e32 100644 --- a/backend/rorapp/functions/__init__.py +++ b/backend/rorapp/functions/__init__.py @@ -1,5 +1,6 @@ # The functions module provides a collection of public functions that are intended to be used by other parts of the application. from .faction_leader_helper import select_faction_leader, set_faction_leader # noqa: F401 +from .forum_phase_helper import initiate_situation # noqa: F401 from .forum_phase_starter import start_forum_phase # noqa: F401 from .game_deleter import delete_all_games # noqa: F401 from .game_generator import generate_game # noqa: F401 diff --git a/backend/rorapp/functions/faction_leader_helper.py b/backend/rorapp/functions/faction_leader_helper.py index b41ba9c7..8267a53b 100644 --- a/backend/rorapp/functions/faction_leader_helper.py +++ b/backend/rorapp/functions/faction_leader_helper.py @@ -2,6 +2,7 @@ from typing import Optional from rorapp.functions.action_helper import delete_old_actions from rorapp.functions.forum_phase_helper import ( + generate_initiate_situation_action, get_next_faction_in_forum_phase, ) from rorapp.functions.mortality_phase_starter import setup_mortality_phase @@ -23,7 +24,6 @@ from rorapp.serializers import ( ActionLogSerializer, ActionSerializer, - StepSerializer, TitleSerializer, SenatorActionLogSerializer, ) @@ -87,7 +87,9 @@ def set_faction_leader(senator_id: int) -> (Response, dict): messages_to_send.extend(proceed_to_next_step_if_forum_phase(game.id, step, faction)) messages_to_send.extend(delete_old_actions(game.id)) - return Response({"message": "Faction leader selected"}, status=200), messages_to_send + return Response( + {"message": "Faction leader selected"}, status=200 + ), messages_to_send def get_previous_title(faction) -> Optional[Title]: @@ -182,30 +184,7 @@ def proceed_to_next_step_if_forum_phase(game_id, step, faction) -> [dict]: next_faction = get_next_faction_in_forum_phase(faction) if next_faction is not None: - new_step = Step(index=step.index + 1, phase=step.phase) - new_step.save() - - messages_to_send.append( - generate_select_faction_leader_action(next_faction, new_step) - ) - - messages_to_send.append( - create_websocket_message("step", StepSerializer(new_step).data) - ) + messages_to_send.extend(generate_initiate_situation_action(next_faction)) else: messages_to_send.extend(start_next_turn(game_id, step)) return messages_to_send - - -def generate_select_faction_leader_action(faction: Faction, step: Step) -> dict: - senators = Senator.objects.filter(faction=faction, death_step__isnull=True) - senator_id_list = [senator.id for senator in senators] - action = Action( - step=step, - faction=faction, - type="select_faction_leader", - required=True, - parameters=senator_id_list, - ) - action.save() - return create_websocket_message("action", ActionSerializer(action).data) diff --git a/backend/rorapp/functions/forum_phase_helper.py b/backend/rorapp/functions/forum_phase_helper.py index 76c09943..91d2f271 100644 --- a/backend/rorapp/functions/forum_phase_helper.py +++ b/backend/rorapp/functions/forum_phase_helper.py @@ -1,5 +1,17 @@ -from typing import Optional -from rorapp.models import Faction +from rest_framework.response import Response +from typing import List, Optional +from rorapp.functions.websocket_message_helper import ( + create_websocket_message, + destroy_websocket_message, +) +from rorapp.models import ( + Action, + Faction, + Phase, + Senator, + Step, +) +from rorapp.serializers import ActionSerializer, StepSerializer def get_next_faction_in_forum_phase( @@ -23,3 +35,81 @@ def get_next_faction_in_forum_phase( if next_faction_index >= len(factions): return None return factions[next_faction_index] + + +def generate_select_faction_leader_action(faction: Faction, step: Step) -> dict: + senators = Senator.objects.filter(faction=faction, death_step__isnull=True) + senator_id_list = [senator.id for senator in senators] + action = Action( + step=step, + faction=faction, + type="select_faction_leader", + required=True, + parameters=senator_id_list, + ) + action.save() + return create_websocket_message("action", ActionSerializer(action).data) + + +def generate_initiate_situation_action(faction: Faction) -> List[dict]: + messages_to_send = [] + + # Create new step + latest_step = Step.objects.filter(phase__turn__game=faction.game.id).order_by( + "-index" + )[0] + # Need to get latest phase because the latest step might not be from the current forum phase + latest_phase = Phase.objects.filter(turn__game=faction.game.id).order_by("-index")[ + 0 + ] + new_step = Step(index=latest_step.index + 1, phase=latest_phase) + new_step.save() + messages_to_send.append( + create_websocket_message("step", StepSerializer(new_step).data) + ) + + # Create new action + action = Action( + step=new_step, + faction=faction, + type="initiate_situation", + required=True, + ) + action.save() + messages_to_send.append( + create_websocket_message("action", ActionSerializer(action).data) + ) + return messages_to_send + + +def initiate_situation(action_id: int) -> dict: + """ + Initiate a random situation. + + This function is called when a player initiates a situation during the forum phase. + + Args: + action_id (int): The action ID. + + Returns: + dict: The response with a message and a status code. + """ + messages_to_send = [] + + # Mark the action as complete + action = Action.objects.get(id=action_id) + action.completed = True + action.save() + messages_to_send.append(destroy_websocket_message("action", action_id)) + + # Create new step + new_step = Step(index=action.step.index + 1, phase=action.step.phase) + new_step.save() + messages_to_send.append( + create_websocket_message("step", StepSerializer(new_step).data) + ) + + messages_to_send.append( + generate_select_faction_leader_action(action.faction, new_step) + ) + return Response({"message": "Situation initiated"}, status=200), messages_to_send diff --git a/backend/rorapp/functions/forum_phase_starter.py b/backend/rorapp/functions/forum_phase_starter.py index 87d5a1e0..7c7721b9 100644 --- a/backend/rorapp/functions/forum_phase_starter.py +++ b/backend/rorapp/functions/forum_phase_starter.py @@ -1,19 +1,25 @@ from typing import List from rorapp.functions.action_helper import delete_old_actions -from rorapp.functions.faction_leader_helper import generate_select_faction_leader_action +from rorapp.functions.forum_phase_helper import generate_initiate_situation_action from rorapp.functions.websocket_message_helper import create_websocket_message from rorapp.models import ( Faction, Phase, Step, ) -from rorapp.serializers import ( - StepSerializer, - PhaseSerializer, -) +from rorapp.serializers import PhaseSerializer + +def start_forum_phase(game_id: int) -> List[dict]: + """ + Start the forum phase. -def start_forum_phase(game_id) -> List[dict]: + Args: + game_id (int): The game ID. + + Returns: + List[dict]: The WebSocket messages to send. + """ messages_to_send = [] latest_step = Step.objects.filter(phase__turn__game=game_id).order_by("-index")[0] @@ -25,16 +31,9 @@ def start_forum_phase(game_id) -> List[dict]: messages_to_send.append( create_websocket_message("phase", PhaseSerializer(new_phase).data) ) - new_step = Step(index=latest_step.index + 1, phase=new_phase) - new_step.save() - messages_to_send.append( - create_websocket_message("step", StepSerializer(new_step).data) - ) - # Create actions + # Create action and new step first_faction = Faction.objects.filter(game__id=game_id).order_by("rank").first() - messages_to_send.append( - generate_select_faction_leader_action(first_faction, new_step) - ) + messages_to_send.extend(generate_initiate_situation_action(first_faction)) messages_to_send.extend(delete_old_actions(game_id)) return messages_to_send diff --git a/backend/rorapp/functions/game_starter.py b/backend/rorapp/functions/game_starter.py index 5ea60b33..622041d4 100644 --- a/backend/rorapp/functions/game_starter.py +++ b/backend/rorapp/functions/game_starter.py @@ -9,7 +9,7 @@ from django.contrib.auth.models import User from rest_framework.response import Response from rest_framework.exceptions import NotFound, PermissionDenied -from rorapp.functions.faction_leader_helper import generate_select_faction_leader_action +from rorapp.functions.forum_phase_helper import generate_select_faction_leader_action from rorapp.functions.rank_helper import rank_senators_and_factions from rorapp.functions.websocket_message_helper import ( send_websocket_messages, diff --git a/backend/rorapp/tests/forum_phase_tests.py b/backend/rorapp/tests/forum_phase_tests.py index e1e70d4d..01bda060 100644 --- a/backend/rorapp/tests/forum_phase_tests.py +++ b/backend/rorapp/tests/forum_phase_tests.py @@ -25,7 +25,7 @@ def test_forum_phase(self) -> None: for player_count in range(3, 7): self.do_forum_phase_test(player_count) - def action_processor(self, action: Action) -> dict: + def faction_leader_action_processor(self, action: Action) -> dict: faction = Faction.objects.filter(player=action.faction.player.id).get( game=action.faction.game.id ) @@ -35,32 +35,48 @@ def action_processor(self, action: Action) -> dict: def do_forum_phase_test(self, player_count: int) -> None: random.seed(1) - game_id, faction_ids_with_leadership = self.setup_game_in_forum_phase(player_count) + game_id, faction_ids_with_leadership = self.setup_game_in_forum_phase( + player_count + ) for _ in range(0, player_count): check_latest_phase(self, game_id, "Forum") - potential_actions = get_and_check_actions( + situation_potential_actions = get_and_check_actions( + self, game_id, False, "initiate_situation", 1 + ) + submit_actions( + self, + game_id, + situation_potential_actions, + self.faction_leader_action_processor, + ) + check_latest_phase(self, game_id, "Forum") + faction_leader_potential_actions = get_and_check_actions( self, game_id, False, "select_faction_leader", 1 ) - self.assertEqual(len(potential_actions), 1) faction_leader_titles = Title.objects.filter( name="Faction Leader", - senator__faction=potential_actions[0].faction, - end_step=None + senator__faction=faction_leader_potential_actions[0].faction, + end_step=None, ) - + # If the faction already has a leader, then there should be no existing faction leader title. - self.assertEqual(len(faction_leader_titles), 1 if potential_actions[0].faction.id in faction_ids_with_leadership else 0) + self.assertEqual( + len(faction_leader_titles), + 1 + if faction_leader_potential_actions[0].faction.id + in faction_ids_with_leadership + else 0, + ) submit_actions( self, game_id, - potential_actions, - self.action_processor, + faction_leader_potential_actions, + self.faction_leader_action_processor, ) - self.assertEqual(len(potential_actions), 1) faction_leader_titles = Title.objects.filter( name="Faction Leader", - senator__faction=potential_actions[0].faction, - end_step=None + senator__faction=faction_leader_potential_actions[0].faction, + end_step=None, ) self.assertEqual(len(faction_leader_titles), 1) check_latest_phase(self, game_id, "Mortality") @@ -72,7 +88,8 @@ def setup_game_in_forum_phase(self, player_count: int) -> (int, List[int]): faction_ids_with_leadership = set_some_faction_leaders(game_id) start_forum_phase(game_id) return (game_id, faction_ids_with_leadership) - + + def set_some_faction_leaders(game_id: int) -> List[int]: """ Assigns faction leader titles to 2 senators then returns their faction IDs. @@ -80,12 +97,15 @@ def set_some_faction_leaders(game_id: int) -> List[int]: factions = Faction.objects.filter(game=game_id) first_faction = factions.first() second_faction = factions.last() - senator_in_faction_1 = Senator.objects.filter(game=game_id, faction=first_faction).first() - senator_in_faction_2 = Senator.objects.filter(game=game_id, faction=second_faction).first() + senator_in_faction_1 = Senator.objects.filter( + game=game_id, faction=first_faction + ).first() + senator_in_faction_2 = Senator.objects.filter( + game=game_id, faction=second_faction + ).first() set_faction_leader(senator_in_faction_1.id) set_faction_leader(senator_in_faction_2.id) return [ senator_in_faction_1.faction.id, senator_in_faction_2.faction.id, ] - diff --git a/backend/rorapp/tests/test_helper.py b/backend/rorapp/tests/test_helper.py index c959266d..e293f8e8 100644 --- a/backend/rorapp/tests/test_helper.py +++ b/backend/rorapp/tests/test_helper.py @@ -1,10 +1,9 @@ from typing import List from django.db.models.query import QuerySet from django.test import TestCase -from rorapp.models import Action, Phase, Senator, Step +from rorapp.models import Action, Phase, Step, Turn from django.contrib.auth.models import User from typing import Callable -from rorapp.functions import set_faction_leader def check_all_actions( @@ -118,8 +117,14 @@ def check_latest_phase( expected_latest_phase_name: str, expected_phase_count: int | None = None, ) -> None: - phases = Phase.objects.filter(turn__game=game_id) + """ + Check that the latest phase has the expected name, and matches the latest step and latest turn. + """ + latest_turn = Turn.objects.filter(game=game_id).order_by("-index").first() + phases = Phase.objects.filter(turn=latest_turn).order_by("-index") if expected_phase_count: test_case.assertEqual(phases.count(), expected_phase_count) - latest_phase = phases[len(phases) - 1] + latest_phase = phases.first() + latest_step = Step.objects.filter(phase__turn=latest_turn).order_by("-index").first() + test_case.assertEqual(latest_phase.id, latest_step.phase.id) test_case.assertEqual(latest_phase.name, expected_latest_phase_name) diff --git a/backend/rorapp/views/submit_action.py b/backend/rorapp/views/submit_action.py index 38f6054c..c4b1ae2d 100644 --- a/backend/rorapp/views/submit_action.py +++ b/backend/rorapp/views/submit_action.py @@ -3,8 +3,12 @@ from rest_framework import viewsets from rest_framework.decorators import action from rest_framework.response import Response -from rorapp.functions import face_mortality, select_faction_leader -from rorapp.functions import send_websocket_messages +from rorapp.functions import ( + face_mortality, + initiate_situation, + select_faction_leader, + send_websocket_messages, +) from rorapp.models import Game, Faction, Step, Action @@ -15,7 +19,9 @@ class SubmitActionViewSet(viewsets.ViewSet): @action(detail=True, methods=["post"]) @transaction.atomic - def submit_action(self, request: HttpRequest, game_id: int, action_id: int | None =None): + def submit_action( + self, request: HttpRequest, game_id: int, action_id: int | None = None + ): # Try to get the game try: game = Game.objects.get(id=game_id) @@ -55,7 +61,9 @@ def submit_action(self, request: HttpRequest, game_id: int, action_id: int | Non return self.perform_action(game.id, action, request) - def perform_action(self, game_id: int, action: Action, request: HttpRequest) -> Response: + def perform_action( + self, game_id: int, action: Action, request: HttpRequest + ) -> Response: response = None messages = None match action.type: @@ -63,6 +71,8 @@ def perform_action(self, game_id: int, action: Action, request: HttpRequest) -> response, messages = select_faction_leader(action.id, request.data) case "face_mortality": response, messages = face_mortality(action.id) + case "initiate_situation": + response, messages = initiate_situation(action.id) case _: return Response({"message": "Action type is invalid"}, status=400) diff --git a/frontend/components/GamePage.tsx b/frontend/components/GamePage.tsx index 01724078..b1c82e19 100644 --- a/frontend/components/GamePage.tsx +++ b/frontend/components/GamePage.tsx @@ -11,7 +11,6 @@ import useWebSocket from "react-use-websocket" import Tabs from "@mui/material/Tabs" import Tab from "@mui/material/Tab" -import Box from "@mui/material/Box" import CircularProgress from "@mui/material/CircularProgress" import { useGameContext } from "@/contexts/GameContext" @@ -621,9 +620,7 @@ const GamePage = (props: GamePageProps) => { {`${game!.name} | Republic of Rome Online`} -
+
diff --git a/frontend/components/ProgressSection.tsx b/frontend/components/ProgressSection.tsx index 4ad5377c..b504228b 100644 --- a/frontend/components/ProgressSection.tsx +++ b/frontend/components/ProgressSection.tsx @@ -72,6 +72,7 @@ const ProgressSection = ({ latestActions }: ProgressSectionProps) => { (f) => f.id === firstPotentialAction.faction ) if (onlyPendingFaction) + console.log("typed actions:", typedActions) waitingForDesc = ( Waiting for{" "} diff --git a/frontend/components/actionDialogs/ActionDialog.module.css b/frontend/components/actionDialogs/ActionDialog.module.css deleted file mode 100644 index 1b58f5c5..00000000 --- a/frontend/components/actionDialogs/ActionDialog.module.css +++ /dev/null @@ -1,11 +0,0 @@ -button.closeButton { - position: absolute; - right: 8px; - top: 8px; -} - -.content { - display: flex; - flex-direction: column; - gap: 16px; -} diff --git a/frontend/components/actionDialogs/ActionDialog.tsx b/frontend/components/actionDialogs/ActionDialog.tsx index 16165f48..39bd4f8a 100644 --- a/frontend/components/actionDialogs/ActionDialog.tsx +++ b/frontend/components/actionDialogs/ActionDialog.tsx @@ -5,6 +5,7 @@ import Collection from "@/classes/Collection" import Action from "@/classes/Action" import SelectFactionLeaderDialog from "./ActionDialog_SelectFactionLeader" import FaceMortalityDialog from "./ActionDialog_FaceMortality" +import InitiateSituationDialog from "./ActionDialog_InitiateSituation" interface ActionDialogProps { actions: Collection @@ -16,6 +17,7 @@ interface ActionDialogProps { const dialogs: { [key: string]: React.ComponentType } = { select_faction_leader: SelectFactionLeaderDialog, face_mortality: FaceMortalityDialog, + initiate_situation: InitiateSituationDialog, } // Dialog box that displays the action that the player must take diff --git a/frontend/components/actionDialogs/ActionDialog_FaceMortality.tsx b/frontend/components/actionDialogs/ActionDialog_FaceMortality.tsx index 1da1d0e9..a6a44ff3 100644 --- a/frontend/components/actionDialogs/ActionDialog_FaceMortality.tsx +++ b/frontend/components/actionDialogs/ActionDialog_FaceMortality.tsx @@ -11,7 +11,6 @@ import CloseIcon from "@mui/icons-material/Close" import Action from "@/classes/Action" import Collection from "@/classes/Collection" -import actionDialogStyles from "./ActionDialog.module.css" import DeadIcon from "@/images/icons/dead.svg" import request from "@/functions/request" import { useAuthContext } from "@/contexts/AuthContext" @@ -33,9 +32,7 @@ const FaceMortalityDialog = (props: FaceMortalityDialogProps) => { } = useAuthContext() const { game } = useGameContext() - const [requiredAction, setRequiredAction] = useState( - null - ) + const [requiredAction, setRequiredAction] = useState(null) // Set required action useEffect(() => { @@ -64,15 +61,13 @@ const FaceMortalityDialog = (props: FaceMortalityDialogProps) => { return ( <> Ready to Face Mortality? - props.setOpen(false)} - > - - +
+ props.setOpen(false)}> + + +
- +
“Death is the wish of some, the relief of many, and the end of all.” Seneca the Younger diff --git a/frontend/components/actionDialogs/ActionDialog_InitiateSituation.tsx b/frontend/components/actionDialogs/ActionDialog_InitiateSituation.tsx new file mode 100644 index 00000000..472fb4f8 --- /dev/null +++ b/frontend/components/actionDialogs/ActionDialog_InitiateSituation.tsx @@ -0,0 +1,86 @@ +import { useEffect, useState } from "react" +import Image from "next/image" +import { + Button, + DialogActions, + DialogContent, + DialogTitle, + IconButton, +} from "@mui/material" +import CloseIcon from "@mui/icons-material/Close" + +import Action from "@/classes/Action" +import Collection from "@/classes/Collection" +import DeadIcon from "@/images/icons/dead.svg" +import request from "@/functions/request" +import { useAuthContext } from "@/contexts/AuthContext" +import { useGameContext } from "@/contexts/GameContext" + +interface InitiateSituationDialogProps { + setOpen: (open: boolean) => void + actions: Collection +} + +// Action dialog allows the player to ready up for mortality +const InitiateSituationDialog = (props: InitiateSituationDialogProps) => { + const { + accessToken, + refreshToken, + setAccessToken, + setRefreshToken, + setUser, + } = useAuthContext() + const { game } = useGameContext() + + const [requiredAction, setRequiredAction] = useState(null) + + // Set required action + useEffect(() => { + const requiredAction = props.actions.asArray.find( + (a) => a.required === true + ) + if (requiredAction) setRequiredAction(requiredAction) + }, [props.actions]) + + // Handle dialog submission + const handleSubmit = async () => { + if (game && requiredAction) { + request( + "POST", + `games/${game.id}/submit-action/${requiredAction.id}/`, + accessToken, + refreshToken, + setAccessToken, + setRefreshToken, + setUser + ) + props.setOpen(false) + } + } + + return ( + <> + Initiate a Situation +
+ props.setOpen(false)}> + + +
+ + +
+

+ You must initiate a random Situation. It could be a Secret, a Senator, an Event, a War or an Enemy Leader. +

+

This feature is incomplete, so nothing actually happens.

+
+
+ + + + + + ) +} + +export default InitiateSituationDialog diff --git a/frontend/components/actionDialogs/ActionDialog_SelectFactionLeader.tsx b/frontend/components/actionDialogs/ActionDialog_SelectFactionLeader.tsx index 3207132b..db2ba50c 100644 --- a/frontend/components/actionDialogs/ActionDialog_SelectFactionLeader.tsx +++ b/frontend/components/actionDialogs/ActionDialog_SelectFactionLeader.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react" +import { useState } from "react" import { Button, DialogActions, @@ -13,7 +13,6 @@ import { useGameContext } from "@/contexts/GameContext" import Action from "@/classes/Action" import Collection from "@/classes/Collection" import Senator from "@/classes/Senator" -import actionDialogStyles from "./ActionDialog.module.css" import { useAuthContext } from "@/contexts/AuthContext" import request from "@/functions/request" @@ -80,15 +79,13 @@ const SelectFactionLeaderDialog = (props: SelectFactionLeaderDialogProps) => { return ( <> Select your Faction Leader - props.setOpen(false)} - > - - +
+ props.setOpen(false)}> + + +
- +

Your Faction Leader will be immune from persuasion attempts. In the unfortunate event of the death of your Faction Leader, his heir will diff --git a/frontend/data/actions.json b/frontend/data/actions.json index 6b30b8af..8cef0b61 100644 --- a/frontend/data/actions.json +++ b/frontend/data/actions.json @@ -6,5 +6,9 @@ "face_mortality": { "sentence": "face mortality", "title": "Face Mortality" + }, + "initiate_situation": { + "sentence": "initiate a situation", + "title": "Initiate Situation" } } From 961deab03aa6a830d29ad7b42818d3880dc620d1 Mon Sep 17 00:00:00 2001 From: Logan Davidson Date: Fri, 2 Feb 2024 17:02:31 +0000 Subject: [PATCH 2/2] Remove unneeded console log --- frontend/components/ProgressSection.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/components/ProgressSection.tsx b/frontend/components/ProgressSection.tsx index b504228b..4ad5377c 100644 --- a/frontend/components/ProgressSection.tsx +++ b/frontend/components/ProgressSection.tsx @@ -72,7 +72,6 @@ const ProgressSection = ({ latestActions }: ProgressSectionProps) => { (f) => f.id === firstPotentialAction.faction ) if (onlyPendingFaction) - console.log("typed actions:", typedActions) waitingForDesc = ( Waiting for{" "}