feat: dynamically cycle ESO, holdfast bounties, hex bounties, & circuit choices #643

Merged
Sainan merged 2 commits from worldstate into main 2024-12-28 09:30:43 -08:00
Owner
No description provided.
coderabbitai[bot] commented 2024-12-28 00:39:14 -08:00 (Migrated from github.com)
Author
Owner

Walkthrough

The pull request introduces modifications to the world state management in the application, specifically in the worldStateController TypeScript file and the worldState.json static response file. The controller now constructs a new worldState object that combines static data with additional properties based on the current time and request parameters. This includes populating arrays for NodeOverrides, SyndicateMissions, and EndlessXpChoices with new logic and hardcoded values.

New interfaces (IWorldState, ISyndicateMission, INodeOverride, and IEndlessXpChoice) have been added to enhance type safety and define the structure of the world state object. The worldState.json file has been updated to remove several entries from the SyndicateMissions, NodeOverrides, and EndlessXpChoices sections, resulting in a streamlined structure that reflects the changes in the dynamic generation approach.

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.
<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- walkthrough_start --> ## Walkthrough The pull request introduces modifications to the world state management in the application, specifically in the `worldStateController` TypeScript file and the `worldState.json` static response file. The controller now constructs a new `worldState` object that combines static data with additional properties based on the current time and request parameters. This includes populating arrays for `NodeOverrides`, `SyndicateMissions`, and `EndlessXpChoices` with new logic and hardcoded values. New interfaces (`IWorldState`, `ISyndicateMission`, `INodeOverride`, and `IEndlessXpChoice`) have been added to enhance type safety and define the structure of the world state object. The `worldState.json` file has been updated to remove several entries from the `SyndicateMissions`, `NodeOverrides`, and `EndlessXpChoices` sections, resulting in a streamlined structure that reflects the changes in the dynamic generation approach. <!-- walkthrough_end --> <!-- announcements_start --> > [!TIP] > CodeRabbit's [docstrings feature](https://docs.coderabbit.ai/finishing-touches/docstrings) is now available as part of our [Early Access Program](https://docs.coderabbit.ai/early-access)! Simply use the command `@coderabbitai generate docstrings` to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on [Discord](https://discord.com/channels/1134356397673414807/1317286905557287022). <!-- announcements_end --> <!-- internal state start --> <!-- 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 --> <!-- internal state end --> <!-- tips_start --> --- Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <details> <summary>🪧 Tips</summary> ### Chat There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai): - Review comments: Directly reply to a review comment made by CodeRabbit. Example: - `I pushed a fix in commit <commit_id>, please review it.` - `Generate unit testing code for this file.` - `Open a follow-up GitHub issue for this discussion.` - Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples: - `@coderabbitai generate unit testing code for this file.` - `@coderabbitai modularize this function.` - PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples: - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.` - `@coderabbitai read src/utils.ts and generate unit testing code.` - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.` - `@coderabbitai help me debug CodeRabbit configuration file.` Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. ### CodeRabbit Commands (Invoked using PR comments) - `@coderabbitai pause` to pause the reviews on a PR. - `@coderabbitai resume` to resume the paused reviews. - `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository. - `@coderabbitai full review` to do a full review from scratch and review all the files again. - `@coderabbitai summary` to regenerate the summary of the PR. - `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR. ([Beta](https://docs.coderabbit.ai/early-access#beta)) - `@coderabbitai resolve` resolve all the CodeRabbit review comments. - `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository. - `@coderabbitai help` to get help. ### Other keywords and placeholders - Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed. - Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description. - Add `@coderabbitai` anywhere in the PR title to generate the title automatically. ### Documentation and Community - Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit. - Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback. - Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements. </details> <!-- tips_end -->
coderabbitai[bot] (Migrated from github.com) reviewed 2024-12-28 00:43:27 -08:00
coderabbitai[bot] (Migrated from github.com) left a comment
Author
Owner

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/controllers/dynamic/worldStateController.ts (5)

6-14: Ensure robust handling of buildLabel

Your approach for assigning BuildLabel is correct. However, if there's a risk of req.query.buildLabel containing unexpected non-string values, consider validating or sanitizing the input before splitting.


18-23: Consider a dynamic _id or removing the hardcoded one

Hardcoding the _id here may cause collisions if used in a real database context. If possible, consider auto-generating _id values for better maintainability.


25-28: Use named constants for bounty cycles

Having the “2.5-hour” or 9,000,000-millisecond interval in code might be unclear to new contributors. Extract it into a named constant or comment to improve clarity and consistency.


29-44: Reduce repetition for SyndicateMissions creation

Two very similar code blocks for “ZarimanSyndicate” and “HexSyndicate” are created. Consider a helper function (e.g., createBountySyndicate) to avoid duplication.


80-86: Interface IWorldState is clear and descriptive

The interface properly represents your top-level structure. Adding optional docs or comments for each property might help future maintainers.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d1bbff99e and 85ceb328f3.

📒 Files selected for processing (2)
  • src/controllers/dynamic/worldStateController.ts (1 hunks)
  • static/fixed_responses/worldState.json (1 hunks)
🔇 Additional comments (7)
src/controllers/dynamic/worldStateController.ts (6)

2-4: Imports are straightforward

These imports look clean. No immediate issues or improvements seem necessary.


16-16: Weekly calculation logic seems correct

Dividing the current time by 604,800,000 (milliseconds/week) is correct. Just ensure you’re comfortable with integer division flooring any decimals.


77-77: Good usage of JSON response

Returning the assembled worldState is straightforward and aligns with Express best practices.


88-95: ISyndicateMission interface looks good

This interface neatly captures relevant mission fields. No immediate changes suggested.


97-107: INodeOverride suits the dynamic node override logic

The optional properties fit well with the diverse override cases. Nicely done.


109-112: IEndlessXpChoice is straightforward

This interface cleanly represents the category and choices.

static/fixed_responses/worldState.json (1)

1089-1089: Empty EndlessXpChoices array is aligned with dynamic injection

By leaving "EndlessXpChoices": [] in the static response, you rely on the controller to populate these choices. This is consistent with your new dynamic logic, but ensure callers know to expect these arrays to be generated at runtime.

**Actionable comments posted: 1** <details> <summary>🧹 Nitpick comments (5)</summary><blockquote> <details> <summary>src/controllers/dynamic/worldStateController.ts (5)</summary><blockquote> `6-14`: **Ensure robust handling of `buildLabel`** Your approach for assigning `BuildLabel` is correct. However, if there's a risk of `req.query.buildLabel` containing unexpected non-string values, consider validating or sanitizing the input before splitting. --- `18-23`: **Consider a dynamic `_id` or removing the hardcoded one** Hardcoding the `_id` here may cause collisions if used in a real database context. If possible, consider auto-generating `_id` values for better maintainability. --- `25-28`: **Use named constants for bounty cycles** Having the “2.5-hour” or 9,000,000-millisecond interval in code might be unclear to new contributors. Extract it into a named constant or comment to improve clarity and consistency. --- `29-44`: **Reduce repetition for SyndicateMissions creation** Two very similar code blocks for “ZarimanSyndicate” and “HexSyndicate” are created. Consider a helper function (e.g., `createBountySyndicate`) to avoid duplication. --- `80-86`: **Interface IWorldState is clear and descriptive** The interface properly represents your top-level structure. Adding optional docs or comments for each property might help future maintainers. </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used: .coderabbit.yaml** **Review profile: CHILL** **Plan: Pro** <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 4d1bbff99e55b8ddac60197a0331f79e780d17e1 and 85ceb328f3e2547e2af6c984c9256b1dd573858d. </details> <details> <summary>📒 Files selected for processing (2)</summary> * `src/controllers/dynamic/worldStateController.ts` (1 hunks) * `static/fixed_responses/worldState.json` (1 hunks) </details> <details> <summary>🔇 Additional comments (7)</summary> <details> <summary>src/controllers/dynamic/worldStateController.ts (6)</summary> `2-4`: **Imports are straightforward** These imports look clean. No immediate issues or improvements seem necessary. --- `16-16`: **Weekly calculation logic seems correct** Dividing the current time by 604,800,000 (milliseconds/week) is correct. Just ensure you’re comfortable with integer division flooring any decimals. --- `77-77`: **Good usage of JSON response** Returning the assembled `worldState` is straightforward and aligns with Express best practices. --- `88-95`: **ISyndicateMission interface looks good** This interface neatly captures relevant mission fields. No immediate changes suggested. --- `97-107`: **INodeOverride suits the dynamic node override logic** The optional properties fit well with the diverse override cases. Nicely done. --- `109-112`: **IEndlessXpChoice is straightforward** This interface cleanly represents the category and choices. </details> <details> <summary>static/fixed_responses/worldState.json (1)</summary> `1089-1089`: **Empty EndlessXpChoices array is aligned with dynamic injection** By leaving `"EndlessXpChoices": []` in the static response, you rely on the controller to populate these choices. This is consistent with your new dynamic logic, but ensure callers know to expect these arrays to be generated at runtime. </details> </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
coderabbitai[bot] (Migrated from github.com) commented 2024-12-28 00:43:25 -08:00
Author
Owner

🛠️ Refactor suggestion

Externalize or document large choice arrays

The logic for “EXC_NORMAL” and “EXC_HARD” is sound, but the large hardcoded arrays can be difficult to manage or update later. Consider externalizing them into a config file or module for easier maintenance.

_:hammer_and_wrench: Refactor suggestion_ **Externalize or document large choice arrays** The logic for “EXC_NORMAL” and “EXC_HARD” is sound, but the large hardcoded arrays can be difficult to manage or update later. Consider externalizing them into a config file or module for easier maintenance. <!-- This is an auto-generated comment by CodeRabbit -->
coderabbitai[bot] (Migrated from github.com) reviewed 2024-12-28 00:54:05 -08:00
coderabbitai[bot] (Migrated from github.com) left a comment
Author
Owner

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/controllers/dynamic/worldStateController.ts (1)

46-75: 🛠️ Refactor suggestion

Externalize choice arrays and improve cycling logic

The current implementation embeds large arrays directly in the code, making maintenance difficult.

Additionally, the modulo operations (week % 12 and week % 8) could lead to inconsistent cycling as they have different periods. Consider normalizing the cycles:

+// Move to a separate config file: src/config/circuitChoices.ts
+export const CIRCUIT_CHOICES = {
+    EXC_NORMAL: [
+        ["Nidus", "Octavia", "Harrow"],
+        // ... rest of the normal choices
+    ],
+    EXC_HARD: [
+        ["Brunt", "Soma", "Vasto", "Solo", "Burston"],
+        // ... rest of the hard choices
+    ]
+} as const;
+
+// In the controller:
+import { CIRCUIT_CHOICES } from "@/config/circuitChoices";
+
+// Use least common multiple for consistent cycling
+const NORMAL_CYCLE = CIRCUIT_CHOICES.EXC_NORMAL.length;
+const HARD_CYCLE = CIRCUIT_CHOICES.EXC_HARD.length;
+const cycleIndex = week % (NORMAL_CYCLE * HARD_CYCLE);
+
+worldState.EndlessXpChoices.push({
+    Category: "EXC_NORMAL",
+    Choices: CIRCUIT_CHOICES.EXC_NORMAL[cycleIndex % NORMAL_CYCLE]
+});
+
+worldState.EndlessXpChoices.push({
+    Category: "EXC_HARD",
+    Choices: CIRCUIT_CHOICES.EXC_HARD[cycleIndex % HARD_CYCLE]
+});
🧹 Nitpick comments (2)
src/controllers/dynamic/worldStateController.ts (2)

7-14: Add type safety for staticWorldState spread

The spread operator usage could potentially include unexpected properties from the static state. Consider explicitly typing the staticWorldState import.

-import staticWorldState from "@/static/fixed_responses/worldState.json";
+import staticWorldState from "@/static/fixed_responses/worldState.json" assert { type: "json" };
+const typedStaticWorldState = staticWorldState as Partial<IWorldState>;

 export const worldStateController: RequestHandler = (req, res) => {
     const worldState: IWorldState = {
-        ...staticWorldState,
+        ...typedStaticWorldState,

80-112: Add JSDoc comments to document interface fields

The interfaces are well-structured, but adding documentation would improve maintainability.

+/**
+ * Represents the complete world state of the game
+ */
 interface IWorldState {
+    /** Current build label of the game */
     BuildLabel: string;
+    /** Current server timestamp */
     Time: number;
     // ... add documentation for other fields
 }

+/**
+ * Represents a syndicate mission with its timing and parameters
+ */
 interface ISyndicateMission {
     // ... add documentation for fields
 }

+/**
+ * Represents an override for a specific node's properties
+ * @remarks Some fields are optional and should be validated before use
+ */
 interface INodeOverride {
     // ... add documentation for fields
 }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85ceb328f3 and 7e23925e5c.

📒 Files selected for processing (1)
  • src/controllers/dynamic/worldStateController.ts (1 hunks)
🔇 Additional comments (1)
src/controllers/dynamic/worldStateController.ts (1)

6-77: Verify cycling mechanics across server restarts

The current implementation relies heavily on timestamp-based calculations. Ensure that cycling remains consistent across server restarts and timezone changes.

Run this script to analyze the consistency of cycling mechanics:

Verification successful

Time-based cycling implementation is robust and timezone-independent

Based on the verification results, the cycling mechanics implementation is well-designed and reliable:

  1. All time calculations use Unix timestamps (milliseconds since epoch) which are timezone-independent:

    • Elite Sanctuary Onslaught: Uses getTime() / 604800000 (week-based)
    • Holdfast & Hex bounties: Uses getTime() / 9000000 (2.5-hour cycles)
    • Circuit choices: Uses the same week calculation
  2. No timezone-dependent methods are used (verified absence of getHours, getMinutes, getDay, getMonth)

  3. No setTimeout/setInterval usage that could affect cycling consistency

  4. All calculations are deterministic and will produce the same results across server restarts

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify cycling consistency by checking for any hardcoded timestamps or timezone dependencies

# Check for timestamp calculations
rg -n "new Date\(\)" --type ts
rg -n "Date\.now" --type ts
rg -n "getTime" --type ts

# Check for timezone-dependent code
rg -n "getHours|getMinutes|getDay|getMonth" --type ts

# Look for other time-related functions that might affect cycling
rg -n "setTimeout|setInterval" --type ts

Length of output: 2285

**Actionable comments posted: 2** <details> <summary>♻️ Duplicate comments (1)</summary><blockquote> <details> <summary>src/controllers/dynamic/worldStateController.ts (1)</summary><blockquote> `46-75`: _:hammer_and_wrench: Refactor suggestion_ **Externalize choice arrays and improve cycling logic** The current implementation embeds large arrays directly in the code, making maintenance difficult. Additionally, the modulo operations (`week % 12` and `week % 8`) could lead to inconsistent cycling as they have different periods. Consider normalizing the cycles: ```diff +// Move to a separate config file: src/config/circuitChoices.ts +export const CIRCUIT_CHOICES = { + EXC_NORMAL: [ + ["Nidus", "Octavia", "Harrow"], + // ... rest of the normal choices + ], + EXC_HARD: [ + ["Brunt", "Soma", "Vasto", "Solo", "Burston"], + // ... rest of the hard choices + ] +} as const; + +// In the controller: +import { CIRCUIT_CHOICES } from "@/config/circuitChoices"; + +// Use least common multiple for consistent cycling +const NORMAL_CYCLE = CIRCUIT_CHOICES.EXC_NORMAL.length; +const HARD_CYCLE = CIRCUIT_CHOICES.EXC_HARD.length; +const cycleIndex = week % (NORMAL_CYCLE * HARD_CYCLE); + +worldState.EndlessXpChoices.push({ + Category: "EXC_NORMAL", + Choices: CIRCUIT_CHOICES.EXC_NORMAL[cycleIndex % NORMAL_CYCLE] +}); + +worldState.EndlessXpChoices.push({ + Category: "EXC_HARD", + Choices: CIRCUIT_CHOICES.EXC_HARD[cycleIndex % HARD_CYCLE] +}); ``` </blockquote></details> </blockquote></details> <details> <summary>🧹 Nitpick comments (2)</summary><blockquote> <details> <summary>src/controllers/dynamic/worldStateController.ts (2)</summary><blockquote> `7-14`: **Add type safety for staticWorldState spread** The spread operator usage could potentially include unexpected properties from the static state. Consider explicitly typing the staticWorldState import. ```diff -import staticWorldState from "@/static/fixed_responses/worldState.json"; +import staticWorldState from "@/static/fixed_responses/worldState.json" assert { type: "json" }; +const typedStaticWorldState = staticWorldState as Partial<IWorldState>; export const worldStateController: RequestHandler = (req, res) => { const worldState: IWorldState = { - ...staticWorldState, + ...typedStaticWorldState, ``` --- `80-112`: **Add JSDoc comments to document interface fields** The interfaces are well-structured, but adding documentation would improve maintainability. ```diff +/** + * Represents the complete world state of the game + */ interface IWorldState { + /** Current build label of the game */ BuildLabel: string; + /** Current server timestamp */ Time: number; // ... add documentation for other fields } +/** + * Represents a syndicate mission with its timing and parameters + */ interface ISyndicateMission { // ... add documentation for fields } +/** + * Represents an override for a specific node's properties + * @remarks Some fields are optional and should be validated before use + */ interface INodeOverride { // ... add documentation for fields } ``` </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used: .coderabbit.yaml** **Review profile: CHILL** **Plan: Pro** <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 85ceb328f3e2547e2af6c984c9256b1dd573858d and 7e23925e5c25b5e11b82b0cc9ddb37895a9d5c73. </details> <details> <summary>📒 Files selected for processing (1)</summary> * `src/controllers/dynamic/worldStateController.ts` (1 hunks) </details> <details> <summary>🔇 Additional comments (1)</summary> <details> <summary>src/controllers/dynamic/worldStateController.ts (1)</summary> `6-77`: **Verify cycling mechanics across server restarts** The current implementation relies heavily on timestamp-based calculations. Ensure that cycling remains consistent across server restarts and timezone changes. Run this script to analyze the consistency of cycling mechanics: <details> <summary>✅ Verification successful</summary> **Time-based cycling implementation is robust and timezone-independent** Based on the verification results, the cycling mechanics implementation is well-designed and reliable: 1. All time calculations use Unix timestamps (milliseconds since epoch) which are timezone-independent: - Elite Sanctuary Onslaught: Uses `getTime() / 604800000` (week-based) - Holdfast & Hex bounties: Uses `getTime() / 9000000` (2.5-hour cycles) - Circuit choices: Uses the same week calculation 2. No timezone-dependent methods are used (verified absence of `getHours`, `getMinutes`, `getDay`, `getMonth`) 3. No setTimeout/setInterval usage that could affect cycling consistency 4. All calculations are deterministic and will produce the same results across server restarts </details> <details> <summary>🏁 Scripts executed</summary> The following scripts were executed for the analysis: Script: ```shell #!/bin/bash # Description: Verify cycling consistency by checking for any hardcoded timestamps or timezone dependencies # Check for timestamp calculations rg -n "new Date\(\)" --type ts rg -n "Date\.now" --type ts rg -n "getTime" --type ts # Check for timezone-dependent code rg -n "getHours|getMinutes|getDay|getMonth" --type ts # Look for other time-related functions that might affect cycling rg -n "setTimeout|setInterval" --type ts ``` Length of output: 2285 </details> </details> </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
@ -14,0 +28,4 @@
const bountyCycleEnd = bountyCycleStart + 9000000;
worldState.SyndicateMissions.push({
_id: { $oid: bountyCycleStart.toString(16) + "0000000000000029" },
Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
coderabbitai[bot] (Migrated from github.com) commented 2024-12-28 00:54:04 -08:00
Author
Owner

🛠️ Refactor suggestion

Improve week calculation precision and document implementation details

A few concerns about this implementation:

  1. The week calculation doesn't account for timezone differences
  2. The "unfaithful" comment needs clarification
  3. The hardcoded OID should be externalized

Consider these improvements:

+const ESO_NODE_ID = "5ad9f9bb6df82a56eabf3d44";
+const ESO_NODE = "SolNode802";
+
+// Calculate week number using UTC to ensure consistent cycling globally
-const week = Math.trunc(new Date().getTime() / 604800000);
+const week = Math.floor(Date.UTC() / (7 * 24 * 60 * 60 * 1000));

 // Elite Sanctuary Onslaught cycling every week
 worldState.NodeOverrides.push({
-    _id: { $oid: "5ad9f9bb6df82a56eabf3d44" },
-    Node: "SolNode802",
+    _id: { $oid: ESO_NODE_ID },
+    Node: ESO_NODE,
     Seed: week // unfaithful
 });

Also, please document why this implementation is considered "unfaithful" to help future maintainers understand the limitations or differences from the original system.

Committable suggestion skipped: line range outside the PR's diff.

_:hammer_and_wrench: Refactor suggestion_ **Improve week calculation precision and document implementation details** A few concerns about this implementation: 1. The week calculation doesn't account for timezone differences 2. The "unfaithful" comment needs clarification 3. The hardcoded OID should be externalized Consider these improvements: ```diff +const ESO_NODE_ID = "5ad9f9bb6df82a56eabf3d44"; +const ESO_NODE = "SolNode802"; + +// Calculate week number using UTC to ensure consistent cycling globally -const week = Math.trunc(new Date().getTime() / 604800000); +const week = Math.floor(Date.UTC() / (7 * 24 * 60 * 60 * 1000)); // Elite Sanctuary Onslaught cycling every week worldState.NodeOverrides.push({ - _id: { $oid: "5ad9f9bb6df82a56eabf3d44" }, - Node: "SolNode802", + _id: { $oid: ESO_NODE_ID }, + Node: ESO_NODE, Seed: week // unfaithful }); ``` Also, please document why this implementation is considered "unfaithful" to help future maintainers understand the limitations or differences from the original system. > Committable suggestion skipped: line range outside the PR's diff. <!-- This is an auto-generated comment by CodeRabbit -->
@ -14,0 +49,4 @@
Choices: [
["Nidus", "Octavia", "Harrow"],
["Gara", "Khora", "Revenant"],
["Garuda", "Baruuk", "Hildryn"],
coderabbitai[bot] (Migrated from github.com) commented 2024-12-28 00:54:04 -08:00
Author
Owner

🛠️ Refactor suggestion

Refactor bounty cycling to reduce duplication and improve precision

The current implementation has several areas for improvement:

  1. Code duplication in bounty mission creation
  2. Magic numbers in cycle calculations
  3. Timestamp conversion inconsistency (using both base 10 and 16)

Consider this refactored approach:

+const BOUNTY_CYCLE_DURATION = 2.5 * 60 * 60 * 1000; // 2.5 hours in milliseconds
+
+interface BountyConfig {
+    tag: string;
+    idSuffix: string;
+}
+
+const bountyTypes: BountyConfig[] = [
+    { tag: "ZarimanSyndicate", idSuffix: "29" },
+    { tag: "HexSyndicate", idSuffix: "06" }
+];
+
-const bountyCycle = Math.trunc(new Date().getTime() / 9000000);
-const bountyCycleStart = bountyCycle * 9000000;
-const bountyCycleEnd = bountyCycleStart + 9000000;
+const now = new Date().getTime();
+const bountyCycle = Math.floor(now / BOUNTY_CYCLE_DURATION);
+const bountyCycleStart = bountyCycle * BOUNTY_CYCLE_DURATION;
+const bountyCycleEnd = bountyCycleStart + BOUNTY_CYCLE_DURATION;
+
+bountyTypes.forEach(({ tag, idSuffix }) => {
+    worldState.SyndicateMissions.push({
+        _id: { $oid: bountyCycleStart.toString(16).padStart(24, '0').slice(0, -2) + idSuffix },
+        Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
+        Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
+        Tag: tag,
+        Seed: bountyCycle,
+        Nodes: []
+    });
+});
-worldState.SyndicateMissions.push({...}); // Remove both push operations
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    const BOUNTY_CYCLE_DURATION = 2.5 * 60 * 60 * 1000; // 2.5 hours in milliseconds

    interface BountyConfig {
        tag: string;
        idSuffix: string;
    }

    const bountyTypes: BountyConfig[] = [
        { tag: "ZarimanSyndicate", idSuffix: "29" },
        { tag: "HexSyndicate", idSuffix: "06" }
    ];

    const now = new Date().getTime();
    const bountyCycle = Math.floor(now / BOUNTY_CYCLE_DURATION);
    const bountyCycleStart = bountyCycle * BOUNTY_CYCLE_DURATION;
    const bountyCycleEnd = bountyCycleStart + BOUNTY_CYCLE_DURATION;

    bountyTypes.forEach(({ tag, idSuffix }) => {
        worldState.SyndicateMissions.push({
            _id: { $oid: bountyCycleStart.toString(16).padStart(24, '0').slice(0, -2) + idSuffix },
            Activation: { $date: { $numberLong: bountyCycleStart.toString() } },
            Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } },
            Tag: tag,
            Seed: bountyCycle,
            Nodes: []
        });
    });
_:hammer_and_wrench: Refactor suggestion_ **Refactor bounty cycling to reduce duplication and improve precision** The current implementation has several areas for improvement: 1. Code duplication in bounty mission creation 2. Magic numbers in cycle calculations 3. Timestamp conversion inconsistency (using both base 10 and 16) Consider this refactored approach: ```diff +const BOUNTY_CYCLE_DURATION = 2.5 * 60 * 60 * 1000; // 2.5 hours in milliseconds + +interface BountyConfig { + tag: string; + idSuffix: string; +} + +const bountyTypes: BountyConfig[] = [ + { tag: "ZarimanSyndicate", idSuffix: "29" }, + { tag: "HexSyndicate", idSuffix: "06" } +]; + -const bountyCycle = Math.trunc(new Date().getTime() / 9000000); -const bountyCycleStart = bountyCycle * 9000000; -const bountyCycleEnd = bountyCycleStart + 9000000; +const now = new Date().getTime(); +const bountyCycle = Math.floor(now / BOUNTY_CYCLE_DURATION); +const bountyCycleStart = bountyCycle * BOUNTY_CYCLE_DURATION; +const bountyCycleEnd = bountyCycleStart + BOUNTY_CYCLE_DURATION; + +bountyTypes.forEach(({ tag, idSuffix }) => { + worldState.SyndicateMissions.push({ + _id: { $oid: bountyCycleStart.toString(16).padStart(24, '0').slice(0, -2) + idSuffix }, + Activation: { $date: { $numberLong: bountyCycleStart.toString() } }, + Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } }, + Tag: tag, + Seed: bountyCycle, + Nodes: [] + }); +}); -worldState.SyndicateMissions.push({...}); // Remove both push operations ``` <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. `````suggestion const BOUNTY_CYCLE_DURATION = 2.5 * 60 * 60 * 1000; // 2.5 hours in milliseconds interface BountyConfig { tag: string; idSuffix: string; } const bountyTypes: BountyConfig[] = [ { tag: "ZarimanSyndicate", idSuffix: "29" }, { tag: "HexSyndicate", idSuffix: "06" } ]; const now = new Date().getTime(); const bountyCycle = Math.floor(now / BOUNTY_CYCLE_DURATION); const bountyCycleStart = bountyCycle * BOUNTY_CYCLE_DURATION; const bountyCycleEnd = bountyCycleStart + BOUNTY_CYCLE_DURATION; bountyTypes.forEach(({ tag, idSuffix }) => { worldState.SyndicateMissions.push({ _id: { $oid: bountyCycleStart.toString(16).padStart(24, '0').slice(0, -2) + idSuffix }, Activation: { $date: { $numberLong: bountyCycleStart.toString() } }, Expiry: { $date: { $numberLong: bountyCycleEnd.toString() } }, Tag: tag, Seed: bountyCycle, Nodes: [] }); }); ````` </details> <!-- suggestion_end --> <!-- This is an auto-generated comment by CodeRabbit -->
Sign in to join this conversation.
No description provided.