Skip to content

Conversation

@Yugesh-Kumar-S
Copy link
Contributor

@Yugesh-Kumar-S Yugesh-Kumar-S commented Aug 17, 2025

Fixes #2797

Changes

  • Created common widgets for experiments.
  • Added light vs distance experiment .

Screenshots / Recordings

screen-20250820-002933.mp4

Checklist:

  • No hard coding: I have used resources from strings.xml, dimens.xml and colors.xml without hard coding any value.
  • No end of file edits: No modifications done at end of resource files strings.xml, dimens.xml or colors.xml.
  • Code reformatting: I have reformatted code and fixed indentation in every file included in this pull request.
  • No extra space: My code does not contain any extra lines or extra spaces than the ones that are necessary.

Summary by Sourcery

Introduce a new experiment framework and create a Light Intensity vs Distance experiment with UI integration and localization support.

New Features:

  • Add experiment framework with ExperimentConfig, ExperimentStep, and ExperimentProvider to manage experiment lifecycles
  • Create ExperimentsScreen and ExperimentGuideScreen to list available experiments and guide users through multi-step procedures
  • Implement ExperimentOverlayWidget to display draggable, step-based instructions over instrument screens and integrate it into LuxMeterScreen

Enhancements:

  • Introduce Light Intensity vs Distance experiment with defined guide steps and condition-check logic
  • Update navigation drawer and main routes to include an Experiments section
  • Add localization entries and theme colors for experiment-related UI elements

Summary by Sourcery

Add a modular experiment framework and integrate a new Light Intensity vs Distance experiment with guided steps, overlay instructions, and localization, along with UI and navigation enhancements.

New Features:

  • Introduce an experiment framework with ExperimentConfig, ExperimentStep, and ExperimentProvider to manage experiments and step progression
  • Add ExperimentsScreen to list available experiments and ExperimentGuideScreen to walk users through multi-step guides
  • Implement a draggable ExperimentOverlayWidget for in-app instruction overlays and integrate it into the LuxMeterScreen for active experiments
  • Create a Light Intensity vs Distance experiment with specific guide steps and condition-check logic

Enhancements:

  • Add localization entries and theme colors for experiment-related UI elements
  • Extend the navigation drawer and routing to include an Experiments section

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Aug 17, 2025

Reviewer's Guide

This PR introduces a generic experiment framework with models and a provider to orchestrate multiscreen experiments, implements a Light Intensity vs Distance experiment with condition-based step logic, adds dedicated experiment navigation and guide screens, augments the LuxMeterScreen to run experiments via a draggable overlay, and updates localization and theme resources accordingly.

Sequence diagram for experiment step condition checking in LuxMeterScreen

sequenceDiagram
    participant LuxMeterScreen
    participant ExperimentProvider
    participant User as actor
    loop Every second (if isExperiment)
      LuxMeterScreen->>ExperimentProvider: checkStepCondition(luxData, timeData)
      alt Step condition met
        ExperimentProvider->>LuxMeterScreen: notifies step completion
        LuxMeterScreen->>User: shows "Step Completed" overlay
        ExperimentProvider->>ExperimentProvider: nextStep() after delay
      else Step not met
        LuxMeterScreen->>User: shows current instruction overlay
      end
    end
Loading

Class diagram for the new experiment framework

classDiagram
    class ExperimentConfig {
      +String id
      +String title
      +String description
      +IconData icon
      +List<Map<String, String>> guideSteps
      +List<ExperimentStep> experimentSteps
      +String targetScreen
    }
    class ExperimentStep {
      +String id
      +String instruction
      +Duration? timeout
      +bool checkCondition(List<double> values, List<double> timeData)
    }
    class ExperimentProvider {
      -ExperimentConfig? _currentExperiment
      -int _currentStepIndex
      -bool _isExperimentActive
      -bool _isStepCompleted
      -Timer? _stepTimer
      -DateTime? _stepStartTime
      -bool _isExperimentCompleted
      +startExperiment(ExperimentConfig experiment)
      +checkStepCondition(List<double> values, List<double> timeData)
      +nextStep()
      +stopExperiment()
    }
    ExperimentConfig "1" *-- "many" ExperimentStep
    ExperimentProvider "1" o-- "1" ExperimentConfig
    ExperimentProvider "1" o-- "1" ExperimentStep
Loading

Class diagram for Light Intensity vs Distance experiment steps

classDiagram
    class MoveTowardsLightStep {
      +checkCondition(List<double> values, List<double> timeData)
    }
    class MoveAwayFromLightStep {
      +checkCondition(List<double> values, List<double> timeData)
    }
    class StabilizeReadingStep {
      +checkCondition(List<double> values, List<double> timeData)
    }
    MoveTowardsLightStep --|> ExperimentStep
    MoveAwayFromLightStep --|> ExperimentStep
    StabilizeReadingStep --|> ExperimentStep
Loading

File-Level Changes

Change Details Files
Introduce experiment framework with models and provider
  • Add ExperimentConfig and ExperimentStep abstractions
  • Implement ExperimentProvider to manage lifecycle, step tracking, and timing
lib/models/experiment_config.dart
lib/models/experiment_step.dart
lib/providers/experiment_provider.dart
Implement Light Intensity vs Distance experiment
  • Define StabilizeReadingStep, MoveTowardsLightStep, MoveAwayFromLightStep with checkCondition logic
  • Create lightDistanceExperiment config with guideSteps and experimentSteps
lib/others/light_distance_experiment.dart
Add experiment navigation and guide UI
  • Create ExperimentsScreen listing available experiments
  • Build ExperimentGuideScreen for step-by-step guidance and launch logic
  • Add navigation drawer entry and update main.dart routes
lib/view/experiments_screen.dart
lib/view/experiment_guide_screen.dart
lib/view/widgets/navigation_drawer.dart
lib/main.dart
Enhance LuxMeterScreen for experiment mode
  • Introduce isExperiment flag to trigger periodic condition checks
  • Embed ExperimentOverlayWidget and handle experiment completion to stop/save data
lib/view/luxmeter_screen.dart
Create draggable experiment overlay widget
  • Implement ExperimentOverlayWidget with draggable instruction card
  • Detect step completion and invoke onExperimentComplete callback
lib/view/widgets/experiment_overlay_widget.dart
Extend localizations and theme for experiments
  • Deduplicate existing localization entries and add new experiment-related keys in app_localizations and translations
  • Add stepCompletedColor to theme/colors for completed steps
lib/l10n/app_localizations.dart
lib/l10n/app_localizations_en.dart
lib/theme/colors.dart

Assessment against linked issues

Issue Objective Addressed Explanation
#2797 Implement an interactive experiment that records light intensity at varying distances from a light source using the Lux sensor.
#2797 Guide the user step-by-step through the experiment.
#2797 Help visualize the change in intensity with distance.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@github-actions
Copy link
Contributor

github-actions bot commented Aug 17, 2025

Build Status

Build successful. APKs to test: https://github.com/fossasia/pslab-app/actions/runs/17190909185/artifacts/3838234406.

Screenshots

Android Screenshots
iPhone Screenshots
iPad Screenshots

@Yugesh-Kumar-S
Copy link
Contributor Author

@sourcery-ai review

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Wrap ExperimentGuideScreen with a ChangeNotifierProvider for ExperimentProvider (and ensure it’s properly disposed) instead of instantiating it manually in initState to avoid potential memory leaks.
  • Refactor the repeated MaterialPageRoute logic in ExperimentsScreen (_buildExperimentCard and button onPressed) into a shared helper to reduce duplication.
  • Split the large ExperimentOverlayWidget build method into smaller widgets or helper methods to improve readability and maintainability.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Wrap ExperimentGuideScreen with a ChangeNotifierProvider for ExperimentProvider (and ensure it’s properly disposed) instead of instantiating it manually in initState to avoid potential memory leaks.
- Refactor the repeated MaterialPageRoute logic in ExperimentsScreen (_buildExperimentCard and button onPressed) into a shared helper to reduce duplication.
- Split the large ExperimentOverlayWidget build method into smaller widgets or helper methods to improve readability and maintainability.

## Individual Comments

### Comment 1
<location> `lib/providers/experiment_provider.dart:39` </location>
<code_context>
+  void checkStepCondition(List<double> values, List<double> timeData) {
+    if (!_isExperimentActive || _isStepCompleted || currentStep == null) return;
+
+    if (_stepStartTime != null &&
+        DateTime.now().difference(_stepStartTime!).inSeconds < 3) {
+      return;
</code_context>

<issue_to_address>
Step condition check includes a hardcoded 3-second delay.

Consider making the delay configurable or documenting the rationale for using a fixed 3-second value.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
  void checkStepCondition(List<double> values, List<double> timeData) {
    if (!_isExperimentActive || _isStepCompleted || currentStep == null) return;

    if (_stepStartTime != null &&
        DateTime.now().difference(_stepStartTime!).inSeconds < 3) {
      return;
    }
=======
  /// The minimum delay (in seconds) before step condition is checked.
  /// Default is 3 seconds to allow system stabilization after step start.
  int stepConditionDelaySeconds = 3;

  void checkStepCondition(List<double> values, List<double> timeData) {
    if (!_isExperimentActive || _isStepCompleted || currentStep == null) return;

    if (_stepStartTime != null &&
        DateTime.now().difference(_stepStartTime!).inSeconds < stepConditionDelaySeconds) {
      return;
    }
>>>>>>> REPLACE

</suggested_fix>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Yugesh-Kumar-S Yugesh-Kumar-S marked this pull request as ready for review August 19, 2025 19:09
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Sorry @Yugesh-Kumar-S, you have reached your weekly rate limit for Sourcery. Please try again later

Copy link
Collaborator

@AsCress AsCress left a comment

Choose a reason for hiding this comment

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

@AsCress
Copy link
Collaborator

AsCress commented Aug 24, 2025

@Yugesh-Kumar-S Nice job ! Please resolve conflicts here.

@marcnause
Copy link
Contributor

@Yugesh-Kumar-S Can you please document somewhere how you created the GIF files? I think it would be very useful to know how you created them if somebody else wants to add experiments at some point in the future.

If this is too much additional effort or if you think it is out of scope for this PR, please open a new issue.

@marcnause marcnause merged commit da43abd into fossasia:flutter Aug 24, 2025
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create experiment for the light intensity vs distance.

3 participants