diff --git a/.gitignore b/.gitignore index a7f1be7..cda3536 100644 --- a/.gitignore +++ b/.gitignore @@ -53,8 +53,8 @@ Thumbs.db # ========================= # Application data # ========================= -test_data/*.json -test_data/*.bak +data/*.json +data/*.bak # But keep example files -!test_data/example.json +!data/example.json diff --git a/example.json b/example.json new file mode 100644 index 0000000..6dba8a4 --- /dev/null +++ b/example.json @@ -0,0 +1,89 @@ +{ + "version": 1, + + "players": [ + { + "id": "e7844fbb-8366-44e4-bb43-89b9eef6ef64", + "name": "Alice" + }, + { + "id": "b7eebce7-cf04-40bc-b80c-400585adb3cd", + "name": "Bob" + }, + { + "id": "f87e6d53-30a2-4dd8-a359-d860404ef2ee", + "name": "Charlie" + }, + { + "id": "056011da-b0c7-4dc7-8b7c-14213a8df009", + "name": "Dave" + }, + { + "id": "50e83cb3-b828-4f1e-ad89-7644a84f3d8c", + "name": "Eve" + } + ], + + "wars": [ + { + "id": "WAR2025", + "name": "Llael War 2025", + "year": 2025, + + "participants": { + "e7844fbb-8366-44e4-bb43-89b9eef6ef64": { + "war_points": 0, + "influence_tokens": 1 + }, + "b7eebce7-cf04-40bc-b80c-400585adb3cd": { + "war_points": 0, + "influence_tokens": 0 + } + }, + + "campaigns": [ + { + "id": "CAMP01", + "name": "Widower's Wood", + "order": 1, + "month" : "June", + "participants": { + "e7844fbb-8366-44e4-bb43-89b9eef6ef64": { "campaign_points": 0 }, + "b7eebce7-cf04-40bc-b80c-400585adb3cd": { "campaign_points": 0 } + }, + + "rounds": [ + { + "number": 1, + "sectors": ["North", "South"], + + "choices": { + "e7844fbb-8366-44e4-bb43-89b9eef6ef64": { "primary": "North", "secondary": "South" }, + "b7eebce7-cf04-40bc-b80c-400585adb3cd": { "primary": "North", "secondary": "South" } + }, + + "battles": [ + { + "sector": "North", + "players": ["e7844fbb-8366-44e4-bb43-89b9eef6ef64", "b7eebce7-cf04-40bc-b80c-400585adb3cd"], + "winner": "e7844fbb-8366-44e4-bb43-89b9eef6ef64", + + "effects": { + "campaign_points": 1, + "grants_influence_token": false + } + } + ], + + "completed": true + } + ], + + "completed": false + } + ], + + "is_completed": false + } + ] +} diff --git a/src/warchron/view/view.py b/src/warchron/view/view.py index 73404ce..31354a1 100644 --- a/src/warchron/view/view.py +++ b/src/warchron/view/view.py @@ -197,14 +197,11 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): def display_players(self, players: List[ParticipantOption]) -> None: table = self.playersTable - table.setSortingEnabled(False) table.setRowCount(len(players)) for row, player in enumerate(players): play_item = QtWidgets.QTableWidgetItem(player.name) play_item.setData(Qt.ItemDataRole.UserRole, player.id) table.setItem(row, 0, play_item) - table.setSortingEnabled(True) - table.sortItems(0, Qt.SortOrder.AscendingOrder) table.resizeColumnsToContents() # Wars view @@ -358,7 +355,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): def display_war_objectives(self, objectives: List[ObjectiveDTO]) -> None: table = self.objectivesTable - table.setSortingEnabled(False) table.clearContents() table.setRowCount(len(objectives)) for row, obj in enumerate(objectives): @@ -367,7 +363,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): name_item.setData(Qt.ItemDataRole.UserRole, obj.id) table.setItem(row, 0, name_item) table.setItem(row, 1, desc_item) - table.setSortingEnabled(True) table.resizeColumnsToContents() def display_war_participants( @@ -376,7 +371,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): objectives: List[ObjectiveDTO], ) -> None: table = self.warParticipantsTable - table.setSortingEnabled(False) table.clearContents() base_cols = ["Player", "Faction", "Victory pts"] headers = ( @@ -404,8 +398,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): table.setItem(row, col, NP_item) col += 1 table.setItem(row, col, token_item) - table.setSortingEnabled(True) - table.sortItems(2, Qt.SortOrder.DescendingOrder) table.resizeColumnsToContents() def _on_major_changed(self, value: int) -> None: @@ -475,7 +467,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): def display_campaign_sectors(self, sectors: List[SectorDTO]) -> None: table = self.sectorsTable - table.setSortingEnabled(False) table.clearContents() table.setRowCount(len(sectors)) for row, sect in enumerate(sectors): @@ -496,8 +487,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): table.setItem(row, 4, minor_item) table.setItem(row, 5, influence_item) table.setItem(row, 6, description_item) - table.setSortingEnabled(True) - table.sortItems(1, Qt.SortOrder.AscendingOrder) table.resizeColumnsToContents() def display_campaign_participants( @@ -506,7 +495,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): objectives: List[ObjectiveDTO], ) -> None: table = self.campaignParticipantsTable - table.setSortingEnabled(False) table.clearContents() base_cols = ["Player", "Leader", "Theme", "Victory pts"] headers = ( @@ -536,8 +524,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): table.setItem(row, col, NP_item) col += 1 table.setItem(row, col, token_item) - table.setSortingEnabled(True) - table.sortItems(3, Qt.SortOrder.DescendingOrder) table.resizeColumnsToContents() # Round page @@ -585,7 +571,6 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): def display_round_choices(self, participants: List[ChoiceDTO]) -> None: table = self.choicesTable - table.setSortingEnabled(False) table.clearContents() table.setRowCount(len(participants)) for row, choice in enumerate(participants): @@ -596,12 +581,10 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): table.setItem(row, 0, participant_item) table.setItem(row, 1, priority_item) table.setItem(row, 2, secondary_item) - table.setSortingEnabled(True) table.resizeColumnsToContents() def display_round_battles(self, sectors: List[BattleDTO]) -> None: table = self.battlesTable - table.setSortingEnabled(False) table.clearContents() table.setRowCount(len(sectors)) table.setIconSize(QSize(32, 16)) @@ -625,5 +608,4 @@ class View(QtWidgets.QMainWindow, Ui_MainWindow): table.setItem(row, 3, vp_item) table.setItem(row, 4, score_item) table.setItem(row, 5, comment_item) - table.setSortingEnabled(True) table.resizeColumnsToContents() diff --git a/test_data/example.json b/test_data/example.json deleted file mode 100644 index 9d3ae2f..0000000 --- a/test_data/example.json +++ /dev/null @@ -1,348 +0,0 @@ -{ - "version": "1.0", - "players": [ - { - "id": "c232f334-3c2d-4e62-9c09-23d045e26bf8", - "name": "Alice" - }, - { - "id": "82ef39f2-ff50-4f3f-af74-d0cee7ec5a84", - "name": "Bob" - }, - { - "id": "d00faaf1-5200-4fb0-bfa7-6b5fe89a4c87", - "name": "Charlie" - }, - { - "id": "d5a430cd-11d3-40d4-bf2a-5771cde3c0a9", - "name": "Dave" - }, - { - "id": "ea00a996-5ff1-4386-8e7f-b16edf821b19", - "name": "Eve" - } - ], - "wars": [ - { - "id": "f39a78d5-83a6-43b9-88c7-64a6e3488412", - "name": "Huge War", - "year": 2026, - "major_value": 2, - "minor_value": 1, - "influence_token": true, - "participants": [ - { - "id": "accc25f2-43a0-4d41-804f-3c8aec853c97", - "player_id": "c232f334-3c2d-4e62-9c09-23d045e26bf8", - "faction": "Humans" - }, - { - "id": "179bdab6-8630-4a92-8fb6-d2637562c66c", - "player_id": "82ef39f2-ff50-4f3f-af74-d0cee7ec5a84", - "faction": "Orcs" - }, - { - "id": "1f734e71-bd5b-4c8e-b200-daaafa57f748", - "player_id": "d00faaf1-5200-4fb0-bfa7-6b5fe89a4c87", - "faction": "Elves" - }, - { - "id": "fd55d0cf-67f6-4b5a-87d0-6f0eabcc84f1", - "player_id": "d5a430cd-11d3-40d4-bf2a-5771cde3c0a9", - "faction": "Dwarves" - } - ], - "objectives": [ - { - "id": "effed73b-a408-425b-a53c-2bb847342b2a", - "name": "Military", - "description": "weapons, facilities, organization, etc." - }, - { - "id": "05480fff-d0f8-43df-a315-f99222b0c38b", - "name": "Spiritual", - "description": "religion, worship, philosophy, etc." - }, - { - "id": "7968f01e-844c-4673-beab-98f8fb837b64", - "name": "Occult", - "description": "esotericism, magic, the supernatural, etc." - }, - { - "id": "4d2aa40f-a5f2-49c4-9c68-9bf221ab8931", - "name": "Political", - "description": "alliances/betrayal, institutions, ideology, etc." - } - ], - "campaigns": [ - { - "id": "0e7f9b46-a3c9-46f6-84b8-d1fe0bc88717", - "name": "Epic Conquest", - "month": 1, - "participants": [ - { - "id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "war_participant_id": "accc25f2-43a0-4d41-804f-3c8aec853c97", - "leader": "Emperor", - "theme": "Empire" - }, - { - "id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "war_participant_id": "179bdab6-8630-4a92-8fb6-d2637562c66c", - "leader": "Warchief", - "theme": "Wild" - }, - { - "id": "237c1291-4331-4242-bd70-bf648185a627", - "war_participant_id": "1f734e71-bd5b-4c8e-b200-daaafa57f748", - "leader": "Lord", - "theme": "Sylvan" - }, - { - "id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "war_participant_id": "fd55d0cf-67f6-4b5a-87d0-6f0eabcc84f1", - "leader": "King", - "theme": "Mines" - } - ], - "sectors": [ - { - "id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "name": "Village", - "round_id": "9771379e-12ae-4d55-ad55-65c08ed95dcd", - "major_objective_id": "effed73b-a408-425b-a53c-2bb847342b2a", - "minor_objective_id": "05480fff-d0f8-43df-a315-f99222b0c38b", - "influence_objective_id": "4d2aa40f-a5f2-49c4-9c68-9bf221ab8931", - "mission": "Capture the flag", - "description": "Wooden houses and windmill" - }, - { - "id": "02f3e570-b395-4ea9-b9b6-61eea182c754", - "name": "Suburbs", - "round_id": "9771379e-12ae-4d55-ad55-65c08ed95dcd", - "major_objective_id": "7968f01e-844c-4673-beab-98f8fb837b64", - "minor_objective_id": "05480fff-d0f8-43df-a315-f99222b0c38b", - "influence_objective_id": null, - "mission": "Hold the line", - "description": "Bare shacks and ruined fabrics" - }, - { - "id": "4548997e-50e5-493a-b751-483f5bcccc00", - "name": "Riverside", - "round_id": "4402eb72-bd50-4120-947c-c1a24a8c3117", - "major_objective_id": "05480fff-d0f8-43df-a315-f99222b0c38b", - "minor_objective_id": "7968f01e-844c-4673-beab-98f8fb837b64", - "influence_objective_id": "4d2aa40f-a5f2-49c4-9c68-9bf221ab8931", - "mission": "Zone control", - "description": "Large river with massive bridge" - }, - { - "id": "4237c185-5d15-4cfc-bd99-669fa8ea2aeb", - "name": "Mountains", - "round_id": "4402eb72-bd50-4120-947c-c1a24a8c3117", - "major_objective_id": "effed73b-a408-425b-a53c-2bb847342b2a", - "minor_objective_id": "7968f01e-844c-4673-beab-98f8fb837b64", - "influence_objective_id": null, - "mission": "Annihilation", - "description": "Cliffs and steep landscapestrghs" - }, - { - "id": "d1f7c6cf-40ff-42b8-b1b6-05576017de1f", - "name": "Underground", - "round_id": "a985f5a7-c411-4e31-98fb-8402503880a0", - "major_objective_id": "7968f01e-844c-4673-beab-98f8fb837b64", - "minor_objective_id": "05480fff-d0f8-43df-a315-f99222b0c38b", - "influence_objective_id": null, - "mission": "Double zone", - "description": "Dirty sewers" - }, - { - "id": "096da98e-d8b4-4c71-946a-3cee2cc38499", - "name": "Castle", - "round_id": "a985f5a7-c411-4e31-98fb-8402503880a0", - "major_objective_id": "effed73b-a408-425b-a53c-2bb847342b2a", - "minor_objective_id": "05480fff-d0f8-43df-a315-f99222b0c38b", - "influence_objective_id": "4d2aa40f-a5f2-49c4-9c68-9bf221ab8931", - "mission": "Siege", - "description": "Massive dungon with high walls." - } - ], - "rounds": [ - { - "id": "4402eb72-bd50-4120-947c-c1a24a8c3117", - "choices": [ - { - "participant_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "priority_sector_id": "4548997e-50e5-493a-b751-483f5bcccc00", - "secondary_sector_id": "4237c185-5d15-4cfc-bd99-669fa8ea2aeb", - "comment": null - }, - { - "participant_id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "priority_sector_id": "4237c185-5d15-4cfc-bd99-669fa8ea2aeb", - "secondary_sector_id": "4548997e-50e5-493a-b751-483f5bcccc00", - "comment": null - }, - { - "participant_id": "237c1291-4331-4242-bd70-bf648185a627", - "priority_sector_id": "4237c185-5d15-4cfc-bd99-669fa8ea2aeb", - "secondary_sector_id": "4548997e-50e5-493a-b751-483f5bcccc00", - "comment": null - }, - { - "participant_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "priority_sector_id": "4548997e-50e5-493a-b751-483f5bcccc00", - "secondary_sector_id": "4237c185-5d15-4cfc-bd99-669fa8ea2aeb", - "comment": null - } - ], - "battles": [ - { - "sector_id": "4548997e-50e5-493a-b751-483f5bcccc00", - "player_1_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "player_2_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "winner_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "score": "3/0", - "victory_condition": "Mission", - "comment": "Domination all along." - }, - { - "sector_id": "4237c185-5d15-4cfc-bd99-669fa8ea2aeb", - "player_1_id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "player_2_id": "237c1291-4331-4242-bd70-bf648185a627", - "winner_id": "237c1291-4331-4242-bd70-bf648185a627", - "score": "1/2", - "victory_condition": "Assassination", - "comment": "Stable control until sneaky plot twist." - } - ], - "is_over": true - }, - { - "id": "9771379e-12ae-4d55-ad55-65c08ed95dcd", - "choices": [ - { - "participant_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "priority_sector_id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "secondary_sector_id": "02f3e570-b395-4ea9-b9b6-61eea182c754", - "comment": null - }, - { - "participant_id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "priority_sector_id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "secondary_sector_id": "02f3e570-b395-4ea9-b9b6-61eea182c754", - "comment": null - }, - { - "participant_id": "237c1291-4331-4242-bd70-bf648185a627", - "priority_sector_id": "02f3e570-b395-4ea9-b9b6-61eea182c754", - "secondary_sector_id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "comment": null - }, - { - "participant_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "priority_sector_id": "02f3e570-b395-4ea9-b9b6-61eea182c754", - "secondary_sector_id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "comment": null - } - ], - "battles": [ - { - "sector_id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "player_1_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "player_2_id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "winner_id": null, - "score": "2/2", - "victory_condition": "Draw", - "comment": "Long holding but no overcome..." - }, - { - "sector_id": "02f3e570-b395-4ea9-b9b6-61eea182c754", - "player_1_id": "237c1291-4331-4242-bd70-bf648185a627", - "player_2_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "winner_id": "237c1291-4331-4242-bd70-bf648185a627", - "score": "3/2", - "victory_condition": "Mission", - "comment": "Impressive battle with tactical moves." - } - ], - "is_over": true - }, - { - "id": "a985f5a7-c411-4e31-98fb-8402503880a0", - "choices": [ - { - "participant_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "priority_sector_id": null, - "secondary_sector_id": null, - "comment": null - }, - { - "participant_id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "priority_sector_id": null, - "secondary_sector_id": null, - "comment": null - }, - { - "participant_id": "237c1291-4331-4242-bd70-bf648185a627", - "priority_sector_id": null, - "secondary_sector_id": null, - "comment": null - }, - { - "participant_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "priority_sector_id": null, - "secondary_sector_id": null, - "comment": null - } - ], - "battles": [ - { - "sector_id": "d1f7c6cf-40ff-42b8-b1b6-05576017de1f", - "player_1_id": "602e2eaf-297e-490b-b0e9-efec818e466a", - "player_2_id": "237c1291-4331-4242-bd70-bf648185a627", - "winner_id": null, - "score": null, - "victory_condition": "tie", - "comment": "Never finished..." - }, - { - "sector_id": "096da98e-d8b4-4c71-946a-3cee2cc38499", - "player_1_id": "1f6b4e7c-b1e4-4a2e-9aea-7bb75b20b4de", - "player_2_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "winner_id": "876a1684-7fe2-4d8d-a50a-a4d7e354c5b0", - "score": "4/2", - "victory_condition": "Mission", - "comment": "Decisive fast attack impossible to resist." - } - ], - "is_over": false - } - ], - "is_over": false - } - ], - "events": [ - { - "type": "InfluenceGained", - "id": "8f20b587-0ff3-42c9-9965-88112e2a4e74", - "participant_id": "accc25f2-43a0-4d41-804f-3c8aec853c97", - "context_type": "battle", - "context_id": "4548997e-50e5-493a-b751-483f5bcccc00", - "timestamp": "2026-02-26T16:10:54.125407", - "amount": 1 - }, - { - "type": "TieResolved", - "id": "c83a9d4e-4620-47de-93c8-d29d6e119c59", - "participant_id": null, - "context_type": "battle", - "context_id": "79accf7c-2d93-4ac3-b747-e7092bfe3feb", - "timestamp": "2026-02-26T16:11:44.346337", - "score_value": null - } - ], - "is_over": false - } - ] -} \ No newline at end of file