Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZO disc scanner #2598

Merged
merged 3 commits into from
Jan 18, 2025
Merged

ZO disc scanner #2598

merged 3 commits into from
Jan 18, 2025

Conversation

frzyc
Copy link
Owner

@frzyc frzyc commented Jan 17, 2025

Describe your changes

Pretty bare bones ZZZ scanner inspired by GO implementation.
Screenshot 2025-01-17 004637

  • update IDisc substats to use "upgrades" instead of values

Does not scan location/lock/trash.
Seems that "Shockstar Disco" has an issue due to a unique text wrap-> OCR issue where OCR does not read "[2]" on the second line properly. Can be mitigated via inferring from mainstat(not 100%)

Issue or discord link

Testing/validation

Checklist before requesting a review (leave this PR as draft if any part of this list is not done.)

  • I have commented my code in hard-to understand areas.
  • I have made corresponding changes to README or wiki.
  • For front-end changes, I have updated the corresponding English translations.
  • I have run yarn run mini-ci locally to validate format and lint.
  • If I have added a new library or app, I have updated the deployment scripts to ignore changes as needed

Summary by CodeRabbit

Based on the comprehensive changes, here are the updated release notes:

  • New Features

    • Added disc scanning functionality with image processing and OCR support.
    • Introduced a new library for disc-related utilities and scanning.
  • Improvements

    • Updated disc substat handling to use upgrades instead of direct values.
    • Enhanced image processing and text extraction capabilities.
    • Refined disc editor with new upload and scanning features.
    • Improved accessibility of certain image processing functions.
  • Changes

    • Refactored interfaces and data structures for discs and substats.
    • Modified parsing and validation logic for disc-related data.
    • Updated prop handling in various components for better functionality.
  • Development

    • Added new configuration files for TypeScript, ESLint, and Babel.
    • Introduced utility functions for disc data management.
    • Enhanced documentation and README files for better guidance.

Copy link
Contributor

coderabbitai bot commented Jan 17, 2025

Walkthrough

This pull request introduces a comprehensive set of changes across multiple libraries, focusing on enhancing the disc scanning, processing, and management functionality. The modifications primarily involve restructuring how substats are handled, updating interfaces, introducing new utility functions for image processing, and creating a new disc scanner library. Key changes include transitioning from a value-based to an upgrades-based substat representation and adding robust image scanning capabilities.

Changes

File Change Summary
libs/common/img-util/src/processing.ts Made thresholdFilter and invertColors functions public
libs/zzz/consts/src/disc.ts Renamed functions and variables for clarity
libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts Updated substat handling to use upgrades instead of value
libs/zzz/db/src/Interfaces/IDbDisc.ts Removed ICachedSubstat interface, modified ICachedDisc
libs/zzz/db/src/Interfaces/IDisc.ts Updated ISubstat to use upgrades instead of value
libs/zzz/disc-scanner/ New library with comprehensive scanning utilities
libs/zzz/ui/src/Disc/DiscEditor/DiscEditor.tsx Enhanced image upload and scanning capabilities
libs/zzz/ui/src/Disc/DiscCard.tsx Updated SubstatDisplay to utilize upgrades and rarity
libs/zzz/ui/src/Disc/DiscEditor/SubstatInput.tsx Modified input handling for substats with new rarity prop

Sequence Diagram

sequenceDiagram
    participant User
    participant DiscEditor
    participant ScanningQueue
    participant ImageProcessor
    participant OCR

    User->>DiscEditor: Upload Image
    DiscEditor->>ScanningQueue: Add Image File
    ScanningQueue->>ImageProcessor: Process Image
    ImageProcessor->>OCR: Extract Text
    OCR-->>ImageProcessor: Return Text Data
    ImageProcessor-->>ScanningQueue: Return Processed Result
    ScanningQueue-->>DiscEditor: Update Scanning Status
    DiscEditor->>User: Display Scanned Disc Information
Loading

Possibly related PRs

  • minor updates to relic/lightcone/character stat display #2521: This PR involves updates to the display of statistics, including substats, which relates to the changes made in the main PR that enhance the accessibility of functions related to image processing and potentially affect how statistics are displayed.
  • Replace misread characters while parsing substat #2577: This PR introduces a mapping for misread characters during the parsing of substats, which is relevant to the changes in the main PR that involve functions related to image processing and data extraction, potentially impacting how substats are interpreted.

Suggested labels

SRO

Poem

🐰 Hop, hop, scanning discs with glee,
Pixels dance, text breaks free!
From value to upgrades, we transform,
A rabbit's code, beyond the norm!
Scanning magic, image's art! 🔍

Finishing Touches

  • 📝 Generate Docstrings (Beta)

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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

@frzyc frzyc added the ZO Zenless Optimizer label Jan 17, 2025
@frzyc frzyc requested a review from nguyentvan7 January 17, 2025 05:56
Copy link
Contributor

github-actions bot commented Jan 17, 2025

[zzz-frontend] [Fri Jan 17 05:58:06 UTC 2025] - Deployed 5d7e6d1 to https://genshin-optimizer-prs.github.io/pr/2598/zzz-frontend (Takes 3-5 minutes after this completes to be available)

[sr-frontend] [Fri Jan 17 05:58:30 UTC 2025] - Deployed 5d7e6d1 to https://genshin-optimizer-prs.github.io/pr/2598/sr-frontend (Takes 3-5 minutes after this completes to be available)

[frontend] [Fri Jan 17 05:58:47 UTC 2025] - Deployed 5d7e6d1 to https://genshin-optimizer-prs.github.io/pr/2598/frontend (Takes 3-5 minutes after this completes to be available)

[sr-frontend] [Fri Jan 17 06:16:58 UTC 2025] - Deployed 755a9da to https://genshin-optimizer-prs.github.io/pr/2598/sr-frontend (Takes 3-5 minutes after this completes to be available)

[zzz-frontend] [Fri Jan 17 06:17:07 UTC 2025] - Deployed 755a9da to https://genshin-optimizer-prs.github.io/pr/2598/zzz-frontend (Takes 3-5 minutes after this completes to be available)

[frontend] [Fri Jan 17 06:17:15 UTC 2025] - Deployed 755a9da to https://genshin-optimizer-prs.github.io/pr/2598/frontend (Takes 3-5 minutes after this completes to be available)

[zzz-frontend] [Sat Jan 18 05:12:30 UTC 2025] - Deployed 1cba715 to https://genshin-optimizer-prs.github.io/pr/2598/zzz-frontend (Takes 3-5 minutes after this completes to be available)

[frontend] [Sat Jan 18 05:13:30 UTC 2025] - Deployed 1cba715 to https://genshin-optimizer-prs.github.io/pr/2598/frontend (Takes 3-5 minutes after this completes to be available)

[sr-frontend] [Sat Jan 18 05:13:47 UTC 2025] - Deployed 1cba715 to https://genshin-optimizer-prs.github.io/pr/2598/sr-frontend (Takes 3-5 minutes after this completes to be available)

[Sat Jan 18 14:51:38 UTC 2025] - Deleted deployment

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🔭 Outside diff range comments (2)
libs/zzz/ui/src/Disc/DiscEditor/DiscEditor.tsx (1)

Line range hint 166-170: Fix substat removal logic in setSubstat function

The filter method doesn't modify the substats array in place. Without assigning the filtered array back, the substat at the specified index won't be removed as intended.

Apply this diff to correct the issue:

const setSubstat = useCallback(
  (index: number, substat?: ISubstat) => {
    const substats = [...(disc.substats || [])]
    if (substat) substats[index] = substat
-   else substats.filter((_, i) => i !== index)
+   else substats = substats.filter((_, i) => i !== index)
    setDisc({ substats })
  },
  [disc, setDisc]
)
libs/zzz/db/src/Interfaces/IDisc.ts (1)

Make location, lock, and trash properties optional in IDisc interface

The verification confirms that these properties are not supported by the scanner:

  • The scanner sets them to default values (location: '', lock: false, trash: false)
  • No validation logic exists for these properties
  • No documentation about these limitations

Since these appear to be metadata properties managed outside the scanner, they should be marked as optional in the interface.

🔗 Analysis chain

Line range hint 19-21: Address unsupported scanner features.

The interface includes location, lock, and trash properties, but according to the PR description, these features are not yet supported by the scanner. Consider:

  1. Making these properties optional
  2. Adding validation in the scanner
  3. Documenting the scanner limitations

Let's check if there's any validation for these unsupported features:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for validation of unsupported features
rg -t typescript "location|lock|trash" ./libs/zzz/disc-scanner/

Length of output: 100


Script:

#!/bin/bash
# Search for property usage in TypeScript files
rg "location|lock|trash" --glob "*.{ts,tsx}" ./libs/zzz/disc-scanner/

# Look for validation-related files
fd -e ts -e tsx . ./libs/zzz/disc-scanner/ | grep -i "valid\|scanner"

# Check for documentation
fd "README|DOCS" -e md ./libs/zzz/disc-scanner/

Length of output: 681


Script:

#!/bin/bash
# Check processImg.ts implementation
cat ./libs/zzz/disc-scanner/src/lib/processImg.ts

# Check parse.ts for validation
cat ./libs/zzz/disc-scanner/src/lib/parse.ts

# Check documentation
cat ./libs/zzz/disc-scanner/README.md

Length of output: 10331

🧹 Nitpick comments (18)
libs/zzz/disc-scanner/tsconfig.lib.json (1)

23-23: Consider restricting to TypeScript files only.

Since this is a new TypeScript library, you might want to consider restricting the includes to just TypeScript files (*.ts, *.tsx) unless there's a specific need for JavaScript files.

-  "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
+  "include": ["src/**/*.ts", "src/**/*.tsx"]
libs/zzz/ui/src/Disc/DiscEditor/ScanningUtil.tsx (1)

34-36: Simplify nested await statements for readability

The nested await statements can be flattened to improve code clarity.

Apply this diff to simplify the code:

    async (scheduler) =>
-      (await (
-        await scheduler
-      ).addJob('recognize', canvas, options)) as RecognizeResult
+    async (schedulerPromise) => {
+      const scheduler = await schedulerPromise
+      const result = await scheduler.addJob('recognize', canvas, options)
+      return result as RecognizeResult
+    }
libs/zzz/disc-scanner/src/lib/processImg.ts (1)

125-129: Avoid defaulting to a specific set key without detection

Defaulting to 'AstralVoice' when the set key is not detected may lead to incorrect data entries. Consider prompting the user for input or marking the disc as incomplete.

You might modify the code to handle this case more appropriately, such as:

-      setKey = 'AstralVoice'
-      retProcessed.texts.push(
-        'Could not detect set key. Assuming Astral Voice.'
-      )
+      retProcessed.texts.push(
+        'Could not detect set key. Please verify and enter the correct set.'
+      )
libs/zzz/ui/src/Disc/DiscEditor/DiscEditor.tsx (2)

254-256: Ensure consistent event listener management

If allowUpload changes over time, the event listener for the paste event might not be correctly added or removed, leading to unexpected behavior. Consider using a ref to store allowUpload or restructuring the effect to handle updates.

You might revise the effect to ensure it handles allowUpload changes:

-useEffect(() => {
+useEffect(() => {
+  if (!allowUpload) return
   const pasteFunc = (e: Event) => {
     // Existing code...
   }
-  allowUpload && window.addEventListener('paste', pasteFunc)
+  window.addEventListener('paste', pasteFunc)
   return () => {
-    if (allowUpload) window.removeEventListener('paste', pasteFunc)
+    window.removeEventListener('paste', pasteFunc)
   }
-}, [uploadFiles, allowUpload])
+}, [uploadFiles, allowUpload])

221-226: Reset input value after file selection to allow re-upload

Directly assigning an empty string to e.target.value may not consistently reset the file input in all browsers. To ensure the input is reset properly, consider using a ref or creating a new input element.

Alternatively, you can reset the input by setting the value to null:

  (e: ChangeEvent<HTMLInputElement>) => {
    if (!e.target) return
    uploadFiles(e.target.files)
-   e.target.value = '' // reset the value so the same file can be uploaded again...
+   e.target.value = null // Reset the input
  },
libs/zzz/ui/src/util/isDev.ts (1)

1-7: Add type safety for environment variables.

While the implementation is correct, consider adding type safety for environment variables to prevent runtime issues.

+declare global {
+  namespace NodeJS {
+    interface ProcessEnv {
+      NODE_ENV: 'development' | 'production' | 'test'
+      NX_SHOW_DEV_COMPONENTS?: string
+    }
+  }
+}

 export const isDev = process.env['NODE_ENV'] === 'development'
libs/zzz/disc-scanner/src/lib/consts.ts (2)

3-8: Consider expanding character mapping for OCR corrections.

Given the PR objective mentions OCR issues with text wrapping, consider expanding the misreadCharactersInSubstatMap to handle more common OCR misreadings.

 export const misreadCharactersInSubstatMap = [
   {
     pattern: /#/,
     replacement: '+',
   },
+  {
+    pattern: /[Oo0]/,
+    replacement: '0',
+  },
+  {
+    pattern: /[Il1]/,
+    replacement: '1',
+  },
 ]

10-14: Add type literal for Color values.

Consider using a more specific type for color values to ensure they stay within valid RGB ranges.

+type RGBValue = 0 | 1 | 2 | /* ... */ | 254 | 255

 export const blackColor: Color = {
-  r: 0,
-  g: 0,
-  b: 0,
+  r: 0 as RGBValue,
+  g: 0 as RGBValue,
+  b: 0 as RGBValue,
 }
libs/zzz/db/src/Interfaces/IDisc.ts (2)

11-11: Consider using a more specific type for upgrades count.

Since upgrades represent discrete improvements, consider using a union type to enforce valid values.

-  upgrades: number // This is the number of upgrades this sub receives.
+  upgrades: 0 | 1 | 2 | 3 | 4 | 5 // Maximum upgrades possible

16-16: Enforce level range with type.

Instead of relying on a comment, consider enforcing the level range through types.

-  level: number // 0-15
+  type DiscLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
+  level: DiscLevel
libs/zzz/disc-scanner/src/lib/enStringMap.ts (2)

12-27: Standardize naming patterns in statMapEngMap.

There are inconsistencies in the naming patterns:

  • Some keys end with underscore (e.g., hp_, atk_)
  • Some don't (e.g., anomProf)
  • Some use camelCase (e.g., enerRegen_)

Consider standardizing the naming pattern across all keys for better maintainability.


29-31: Consider pre-computing elemental damage bonus mappings.

The current implementation dynamically generates elemental damage bonus entries on every import. Consider pre-computing these values to avoid unnecessary iterations.

-Object.entries(elementalData).forEach(([e, name]) => {
-  statMapEngMap[`${e}_dmg_`] = `${name} DMG Bonus`
-})
+const elementalDmgMap = Object.fromEntries(
+  Object.entries(elementalData).map(([e, name]) => 
+    [`${e}_dmg_`, `${name} DMG Bonus`]
+  )
+)
+Object.assign(statMapEngMap, elementalDmgMap)
libs/zzz/ui/src/Disc/DiscMainStatDropdown.tsx (1)

46-59: Consider memoizing MenuItem components.

The MenuItems are recreated on every render. Consider memoizing them to improve performance, especially if the list is long.

+const MainStatMenuItem = memo(function MainStatMenuItem({
+  mk,
+  statKey,
+  setStatKey
+}: {
+  mk: DiscMainStatKey
+  statKey?: DiscMainStatKey
+  setStatKey: (statKey: DiscMainStatKey) => void
+}) {
+  return (
+    <MenuItem
+      key={mk}
+      selected={statKey === mk}
+      disabled={statKey === mk}
+      onClick={() => setStatKey(mk)}
+    >
+      <ListItemIcon>
+        <StatIcon statKey={mk} />
+      </ListItemIcon>
+      <StatDisplay statKey={mk} showPercent disableIcon />
+    </MenuItem>
+  )
+})
libs/zzz/disc-scanner/src/lib/ScanningQueue.tsx (2)

11-12: Consider making queue limits configurable.

The maximum processing and processed counts are hardcoded. Consider making these configurable through constructor parameters to allow for different use cases and environments.

-const maxProcessingCount = 3,
-  maxProcessedCount = 16
+export type ScanningQueueConfig = {
+  maxProcessingCount?: number
+  maxProcessedCount?: number
+}

62-66: Fix typo in variable name.

The variable name procesesd has a typo and should be processed.

-const procesesd = this.processed.shift()
-if (procesesd) this.processQueue()
-return procesesd
+const processed = this.processed.shift()
+if (processed) this.processQueue()
+return processed
libs/zzz/ui/src/Disc/DiscEditor/SubstatInput.tsx (3)

38-52: Remove commented-out validation code.

There's a significant block of commented-out validation code. Either implement the validation or remove the comments to maintain code cleanliness.

-  // let error = '',
-  //   allowedRolls = 0
-
-  // if (disc?.rarity) {
-  //   // Account for the rolls it will need to fill all 4 substates, +1 for its base roll
-  //   const rarity = disc.rarity
-  //   const { numUpgrades, high } = discSubstatRollData[rarity]
-  //   const maxRollNum = numUpgrades + high - 3
-  //   allowedRolls = maxRollNum - value
-  // }
-
-  // if (allowedRolls < 0)
-  //   error =
-  //     error ||
-  //     t('editor.substat.error.noOverRoll', { value: allowedRolls + value })

90-92: Remove commented-out ListItemIcon code.

There's commented-out ListItemIcon code. Either implement the icon or remove the comments.

-              {/* <ListItemIcon>
-                    <StatIcon statKey={k} />
-                  </ListItemIcon> */}

167-175: Add aria-label to Slider component.

The Slider component is missing accessibility attributes.

     <Slider
       value={innerValue}
       step={null}
       disabled={disabled}
       marks={marks}
       min={marks[0]?.value ?? 0}
       max={marks[marks.length - 1]?.value ?? 0}
       onChange={(_e, v) => setinnerValue(v as number)}
       onChangeCommitted={(_e, v) => setValue(v as number)}
       valueLabelDisplay="auto"
       valueLabelFormat={valueLabelFormat}
+      aria-label={t('editor.substat.upgradeSlider')}
     />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between beb669d and 5d38cf4.

📒 Files selected for processing (27)
  • libs/common/img-util/src/processing.ts (2 hunks)
  • libs/zzz/consts/src/disc.ts (2 hunks)
  • libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts (6 hunks)
  • libs/zzz/db/src/Interfaces/IDbDisc.ts (1 hunks)
  • libs/zzz/db/src/Interfaces/IDisc.ts (1 hunks)
  • libs/zzz/disc-scanner/.babelrc (1 hunks)
  • libs/zzz/disc-scanner/.eslintrc.json (1 hunks)
  • libs/zzz/disc-scanner/README.md (1 hunks)
  • libs/zzz/disc-scanner/project.json (1 hunks)
  • libs/zzz/disc-scanner/src/index.ts (1 hunks)
  • libs/zzz/disc-scanner/src/lib/ScanningQueue.tsx (1 hunks)
  • libs/zzz/disc-scanner/src/lib/consts.ts (1 hunks)
  • libs/zzz/disc-scanner/src/lib/enStringMap.ts (1 hunks)
  • libs/zzz/disc-scanner/src/lib/parse.ts (1 hunks)
  • libs/zzz/disc-scanner/src/lib/processImg.ts (1 hunks)
  • libs/zzz/disc-scanner/tsconfig.eslint.json (1 hunks)
  • libs/zzz/disc-scanner/tsconfig.json (1 hunks)
  • libs/zzz/disc-scanner/tsconfig.lib.json (1 hunks)
  • libs/zzz/page-discs/src/index.tsx (1 hunks)
  • libs/zzz/solver/src/common.ts (2 hunks)
  • libs/zzz/ui/src/Disc/DiscCard.tsx (3 hunks)
  • libs/zzz/ui/src/Disc/DiscEditor/DiscEditor.tsx (8 hunks)
  • libs/zzz/ui/src/Disc/DiscEditor/ScanningUtil.tsx (1 hunks)
  • libs/zzz/ui/src/Disc/DiscEditor/SubstatInput.tsx (1 hunks)
  • libs/zzz/ui/src/Disc/DiscMainStatDropdown.tsx (2 hunks)
  • libs/zzz/ui/src/util/isDev.ts (1 hunks)
  • tsconfig.base.json (1 hunks)
✅ Files skipped from review due to trivial changes (7)
  • libs/zzz/disc-scanner/README.md
  • libs/zzz/disc-scanner/src/index.ts
  • libs/zzz/disc-scanner/.babelrc
  • libs/zzz/disc-scanner/tsconfig.eslint.json
  • libs/zzz/disc-scanner/tsconfig.json
  • libs/zzz/disc-scanner/.eslintrc.json
  • libs/zzz/disc-scanner/project.json
🧰 Additional context used
🪛 Biome (1.9.4)
libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts

[error] 360-360: isFinite is unsafe. It attempts a type coercion. Use Number.isFinite instead.

See the MDN documentation for more details.
Unsafe fix: Use Number.isFinite instead.

(lint/suspicious/noGlobalIsFinite)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint
🔇 Additional comments (16)
libs/zzz/disc-scanner/tsconfig.lib.json (3)

1-2: LGTM! Base configuration extension is properly set up.

The configuration correctly extends the base tsconfig.json, maintaining consistency with the project's TypeScript settings.


12-22: LGTM! Test file exclusions are comprehensive.

The configuration properly excludes all test files across different extensions (ts, tsx, js, jsx) and naming patterns (.spec., .test.).


3-11: Verify the output directory path and consider adding scanner-specific types.

The compiler options look good, but since this is a scanner library, you might want to consider:

  1. Adding types for image processing libraries you'll be using
  2. Including OCR-related type definitions if you're planning to use any OCR libraries

Let's verify the output directory structure:

libs/zzz/disc-scanner/src/lib/processImg.ts (2)

141-143: Ensure slotKey is correctly identified when missing

Defaulting the mainStatKey without a detected slotKey may cause inconsistencies. Ensure that the slotKey is identified based on the mainStatKey, or prompt the user for verification.

You might add a check to handle this scenario more robustly.


134-138: Handle undetected rarity and level more cautiously

Assuming a default rarity of 'S' and level 15 when detection fails might lead to inaccurate data. It's better to notify the user and request manual input.

Consider updating the code to reflect this:

-      retProcessed.texts.push(
-        'Could not detect rarity + level, assuming S Lv.15/15'
-      )
-      rarity = 'S'
-      level = 15
+      retProcessed.texts.push(
+        'Could not detect rarity and level. Please verify and enter the correct values.'
+      )
libs/zzz/db/src/Interfaces/IDbDisc.ts (1)

Line range hint 1-6: Verify the impact of interface simplification.

The significant reduction in the ICachedDisc interface (removal of mainStatVal and substats) is a breaking change. While this aligns with the move to an upgrades-based system, we should ensure all consumers of this interface are updated.

Let's verify the usage of this interface across the codebase:

✅ Verification successful

Interface changes appear safe to proceed.

The ICachedDisc interface is not currently used in the codebase, and its simplified structure (only adding an id field to IDisc) aligns well with the upgrades-based system already implemented in the base IDisc interface. The changes can proceed safely.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ICachedDisc usage
rg "ICachedDisc" --type typescript -B 2 -A 2

Length of output: 79


Script:

#!/bin/bash
# First, verify the TypeScript file extensions in the codebase
fd "\.(ts|tsx)$"

# Search for ICachedDisc usage in TypeScript files
rg "ICachedDisc" -g "*.{ts,tsx}" -B 2 -A 2

# Use AST-based search to find interface usage
ast-grep --pattern 'interface $_ extends ICachedDisc'
ast-grep --pattern 'class $_ implements ICachedDisc'
ast-grep --pattern ': ICachedDisc'

Length of output: 73698


Script:

#!/bin/bash
# Check the file history
fd "IDbDisc.ts$" --exec git log -p {} | grep -A 5 -B 5 "ICachedDisc"

# Look for any references in commit messages
git log --grep="ICachedDisc"

# Search for any files that might have been renamed
git log --follow --patch libs/zzz/db/src/Interfaces/IDbDisc.ts

Length of output: 0


Script:

#!/bin/bash
# Check the base IDisc interface
cat libs/zzz/db/src/Interfaces/IDisc.ts

# Look for related files in the Database implementation directory
fd "Disc.*\.(ts|tsx)$" libs/zzz/db/src/Database/

# Check for any implementations in DataManagers
fd "DataManager.*\.(ts|tsx)$" libs/zzz/db/src/Database/DataManagers/

Length of output: 842

libs/zzz/disc-scanner/src/lib/enStringMap.ts (1)

3-10: Consider adding missing elemental types.

The elementalData mapping appears incomplete. Based on common game mechanics, consider adding other elemental types like 'wind', 'quantum', 'imaginary' if they exist in the game.

libs/zzz/page-discs/src/index.tsx (1)

30-37: Consider separating upload handling logic.

The allowUpload prop suggests image upload functionality, but the handling logic isn't immediately clear. Consider extracting the upload handling into a separate component or hook for better maintainability.

Also, verify that onShow and onOpen serve different purposes, as they're both being passed the same function.

✅ Verification successful

The onShow and onOpen props serve different purposes

Looking at the implementation in DiscEditor, onShow is used for queue processing side effects while onOpen handles UI visibility. The current implementation is correct and follows the codebase patterns.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of onShow and onOpen props
rg "onShow|onOpen" --type ts

Length of output: 13968

libs/zzz/ui/src/Disc/DiscCard.tsx (2)

207-211: LGTM!

The SubstatDisplay component is now correctly invoked with the required rarity prop, which is essential for calculating the substat's base value.


Line range hint 285-307: LGTM! Clean implementation of the substat display logic.

The component correctly:

  1. Uses the rarity parameter to get the base value
  2. Multiplies it by the number of upgrades
  3. Formats the result appropriately
libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts (3)

96-98: LGTM!

Clean implementation of the substat mapping that correctly preserves only the necessary fields (key and upgrades).


241-241: LGTM!

The duplicate detection logic has been properly updated to use upgrades instead of value while maintaining the same functionality.

Also applies to: 257-257, 265-265, 283-283


300-310: LGTM!

Clean destructuring of disc properties with proper type annotation.

libs/common/img-util/src/processing.ts (2)

145-145: LGTM!

The thresholdFilter function is now properly exported for use in other modules.


165-165: LGTM!

The invertColors function is now properly exported for use in other modules.

tsconfig.base.json (1)

158-160: LGTM!

The path mapping for the new disc scanner module is correctly configured and maintains the established format.

libs/zzz/solver/src/common.ts Show resolved Hide resolved
libs/zzz/ui/src/Disc/DiscMainStatDropdown.tsx Outdated Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/parse.ts Outdated Show resolved Hide resolved
libs/zzz/consts/src/disc.ts Show resolved Hide resolved
libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (5)
libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts (2)

355-366: Consider adding range validation for upgrades.

The validation for the upgrades property is good, but consider adding a range check to ensure the value is non-negative and within expected bounds.

 if (
   !allDiscSubStatKeys.includes(key as DiscSubStatKey) ||
   typeof upgrades !== 'number' ||
-  !Number.isFinite(upgrades)
+  !Number.isFinite(upgrades) ||
+  upgrades < 0
 )

Line range hint 1-380: Consider adding JSDoc comments for public methods.

While the implementation is solid, adding JSDoc comments for public methods would improve maintainability and help document the transition from value to upgrades based substats.

Example for the parseSubstats function:

/**
 * Parses and validates an array of substats.
 * @param obj - The input object containing substat data
 * @param _rarity - The rarity of the disc
 * @param _allowZeroSub - Whether to allow zero value substats
 * @param _sortSubs - Whether to sort the substats
 * @returns An array of validated substats with upgrade values
 */
libs/zzz/disc-scanner/src/lib/processImg.ts (3)

42-47: Add error handling for invalid ImageData in zzzPreprocessImage.

Currently, the function assumes that pixelData is always valid. Consider adding checks to handle cases where pixelData might be null or undefined to prevent potential runtime errors.


89-97: Consolidate duplicate error messages for clarity.

The error message 'Could not detect main stat, substats or set effect.' is repeated multiple times. Consider defining it once as a constant or using a helper function to avoid duplication and make future changes easier.

Apply this diff to define a constant:

+const ERROR_DETECT_STATS = 'Could not detect main stat, substats or set effect.'

       if (
         mainStatTextIndex === -1 ||
         substatTextIndex === -1 ||
         setEffectTextIndex === -1
       ) {
         retProcessed.texts.push(
-          'Could not detect main stat, substats or set effect.'
+          ERROR_DETECT_STATS
         )
         return retProcessed
       }

173-233: Extract cropDiscCard function into a separate module for clarity.

The cropDiscCard function is sizable and focused on a specific task. Moving it to its own module can improve code organization and reusability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d38cf4 and 7e9f13e.

📒 Files selected for processing (4)
  • libs/common/img-util/src/processing.ts (4 hunks)
  • libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts (6 hunks)
  • libs/zzz/disc-scanner/src/lib/processImg.ts (1 hunks)
  • libs/zzz/ui/src/Disc/DiscMainStatDropdown.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • libs/common/img-util/src/processing.ts
  • libs/zzz/ui/src/Disc/DiscMainStatDropdown.tsx
🔇 Additional comments (3)
libs/zzz/db/src/Database/DataManagers/DiscDataManager.ts (3)

96-98: LGTM! Clean transition to upgrades-based substats.

The change from value to upgrades in the substat mapping is implemented correctly and maintains type safety.


241-241: Verify the duplicate detection logic with test cases.

The transition from value to upgrades comparison in duplicate detection looks correct. However, since this is a critical feature that affects data integrity, comprehensive testing is recommended.

Would you like me to help generate test cases covering various duplicate and upgrade scenarios?

Also applies to: 257-257, 265-265, 283-283


300-310: LGTM! Clean property destructuring.

The destructuring pattern has been improved to be more concise while maintaining completeness.

libs/zzz/disc-scanner/src/lib/processImg.ts Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/processImg.ts Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/processImg.ts Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/processImg.ts Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/processImg.ts Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/processImg.ts Show resolved Hide resolved
@frzyc frzyc changed the title zo disc scanner ZO disc scanner Jan 17, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
libs/zzz/disc-scanner/src/lib/parse.ts (3)

15-32: Add input validation to utility functions.

While the implementation is correct, consider adding defensive programming checks:

 function getBestKeyDist<T extends string>(hams: Array<KeyDist<T>>) {
+  if (!hams.length) return []
   const minHam = Math.min(...hams.map(([, ham]) => ham))
   const keys = hams.filter(([, ham]) => ham === minHam).map(([key]) => key)
   return keys
 }
 function findBestKeyDist<T extends string>(
   str: string,
   keys: readonly T[]
 ): T | undefined {
+  if (!str?.trim()) return undefined
   if (!keys.length) return undefined
   if (keys.length === 1) return keys[0]

53-64: Optimize parseSet function performance.

The current implementation checks all combinations of texts and keys. Consider adding optimizations:

 export function parseSet(texts: string[]) {
+  if (!texts?.length) return undefined
   const kdist: Array<KeyDist<DiscSetKey>> = []
   for (const text of texts) {
+    const setKeyStrTrimmed = text.replace(/\W/g, '')
+    // Early exit on exact match
+    const exactMatch = allDiscSetKeys.find(key => key === setKeyStrTrimmed)
+    if (exactMatch) return exactMatch
     for (const key of allDiscSetKeys) {
-      const setKeyStrTrimmed = text.replace(/\W/g, '')
       kdist.push([key, levenshteinDistance(setKeyStrTrimmed, key)])
     }
   }

84-95: Enhance main stat key matching robustness.

Consider improving the text matching logic:

 export function parseMainStatKeys(texts: string[], slotKey?: DiscSlotKey) {
+  if (!texts?.length) return undefined
   const keys = slotKey ? discSlotToMainStatKeys[slotKey] : allDiscMainStatKeys
   if (keys.length === 1) return keys[0]
   for (const text of texts) {
+    const normalizedText = text.toLowerCase().trim()
     const isPercent = text.includes('%')
     const filteredKeys = keys.filter((key) => isPercent === key.endsWith('_'))
     for (const key of filteredKeys) {
-      if (text.includes(statMapEngMap[key])) return key
+      const statName = statMapEngMap[key].toLowerCase()
+      if (normalizedText.includes(statName)) return key
     }
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e9f13e and 3c5b0c5.

📒 Files selected for processing (1)
  • libs/zzz/disc-scanner/src/lib/parse.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint
🔇 Additional comments (2)
libs/zzz/disc-scanner/src/lib/parse.ts (2)

1-14: LGTM! Well-organized imports with clear separation of concerns.

The imports are properly structured, utilizing TypeScript's type system effectively with clear separation between types, constants, and utility functions.


97-120: Previous review comments about substat parsing remain valid.

The issues mentioned in the previous review about duplicate substats, upgrade validation, and maximum limits are still applicable.

Additionally, consider normalizing the stat string before matching:

 export function parseSubstats(texts: string[]): ISubstat[] {
+  if (!texts?.length) return []
+  const seenKeys = new Set<string>()
   const substats: ISubstat[] = []
   for (let text of texts) {
     // Apply OCR character corrections
     for (const { pattern, replacement } of misreadCharactersInSubstatMap) {
       text = text.replace(pattern, replacement)
     }
     const isPercent = text.includes('%')
     const match = /([a-zA-Z\s]+)\s*(\+(\d))?/.exec(text)
     if (match) {
-      const statStr = match[1].trim()
+      const statStr = match[1].toLowerCase().trim()
       const key = findBestKeyDist(
         statStr,
         allDiscSubStatKeys.filter((key) => isPercent === key.endsWith('_'))
       )
-      if (!key) continue
+      if (!key || seenKeys.has(key)) continue
+      seenKeys.add(key)
+      const upgrade = match[3] ? parseInt(match[3]) + 1 : 1
+      if (upgrade > 5) continue // Max upgrades is 5
       substats.push({
         key,
-        upgrades: match[3] ? parseInt(match[3]) + 1 : 1,
+        upgrades: upgrade,
       })
     }
   }

libs/zzz/disc-scanner/src/lib/parse.ts Show resolved Hide resolved
libs/zzz/disc-scanner/src/lib/parse.ts Show resolved Hide resolved
@@ -0,0 +1,7 @@
export const isDev = process.env['NODE_ENV'] === 'development'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prob should refactor but shrug

@frzyc frzyc merged commit 4d74491 into master Jan 18, 2025
11 checks passed
@frzyc frzyc deleted the zzz_scanner branch January 18, 2025 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ZO Zenless Optimizer
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants