Search code examples
flutterruntime-errorcalculation

flutter simple calculation Function error


When i call the function one time it run perfectly but if i call it again it will show different value and read the different else block please check the code i am attaching the whole class and driver code and output of the following function i think there is error in if else condition block i dont undestand why it is giving different values on calling the function 2nd time if i run it again third time it will give correct output

enum ComponentCondition { missing, damaged, good }
class ComponentModel {
  String name;
  ComponentCondition condition;

  double rate;

  double componentPercent;
  double kerbWeight;
  double componentPrice;

  int lifespan;
  int age;
  ComponentModel(
      {this.name,
      @required this.rate,
      @required this.lifespan,
      @required this.kerbWeight,
      @required this.componentPercent,
      @required this.age});

  int calculatePrice() {
    double weight = (componentPercent * kerbWeight) / 100;
    age = DateTime.now().year - age;
    double scrapValue = weight * rate;
    int i = lifespan ~/ 3;

    if ((condition == ComponentCondition.good ||
            condition == ComponentCondition.damaged) &&
        i == 0) {
      componentPrice = scrapValue;
    } else if (condition == ComponentCondition.good && age < lifespan) {
      if (age >= 0 && age <= i) {
        print('bestconditionPrice');
        componentPrice = scrapValue * 3;
      } else if (age > i && age <= i * 2) {
        componentPrice = scrapValue * 2;
      } else if (age > i * 2 && age < lifespan) {
        componentPrice = scrapValue * 1.5;
      }
    } else if ((age >= lifespan) || condition == ComponentCondition.damaged) {
      componentPrice = scrapValue;
      print('why??????');
    } else
      componentPrice = 0;

    return componentPrice.toInt();
  }

  void updateCondition(ComponentCondition partCondition) {
    condition = partCondition;
  }
}

void main(List<String> args) {
  ComponentModel engine = ComponentModel(
      componentPercent: 18, kerbWeight: 695, rate: 17, lifespan: 13, age: 2021);
  engine.updateCondition(ComponentCondition.good);
  int price = engine.calculatePrice();
  int price2 = engine.calculatePrice();
  print(' price1 :$price');
  print("price2 : $price2");
 
}

this is the output


Solution

  • First, this is a very well asked question, you presented a perfectly reproducable example, so congrats.

    As for your question, I'm not entirely sure what you want to happen, but I will show you what to change, so your compiler will tell you where you go wrong:

    • Use the latest version of Flutter. It supports null-safety.
    • Use the final keyword a lot more. Every variable, that you do not expect to change, make them final. That way, when you do change them by accident, your compiler will throw an error and you will immediately notice.
    • Initialize all data. Null-safety will help you here because you will again get compile errors when you forget.
    • Do not keep instance data, just because you can. If something can be a local variable, make it a local variable.
    • Do keep methods short and concise, so do not go into endless if/then chains when you can simply return and be done with it.

    So after a few best practice changes, your code looks like this:

    enum ComponentCondition { missing, damaged, good }
    
    class ComponentModel {
      String? name;
      ComponentCondition condition = ComponentCondition.good;
    
      final double rate;
      final double componentPercent;
      final double kerbWeight;
      final int lifespan;
      final int age;
      
      ComponentModel(
          {this.name,
          required this.rate,
          required this.lifespan,
          required this.kerbWeight,
          required this.componentPercent,
          required this.age });
    
      int calculatePrice() {
        final weight = (componentPercent * kerbWeight) / 100;
        final double scrapValue = weight * rate;
        final i = lifespan ~/ 3;
        
        age = DateTime.now().year - age;
    
        if ((condition == ComponentCondition.good || condition == ComponentCondition.damaged) && i == 0) {
          return scrapValue.toInt();
        }
        
        if (condition == ComponentCondition.good && age < lifespan) {
          if (age >= 0 && age <= i) {
            print('bestconditionPrice');
            return (scrapValue * 3).toInt();
          } 
          
          if (age > i && age <= i * 2) {
            return (scrapValue * 2).toInt();
          } 
          
          if (age > i * 2 && age < lifespan) {
            return (scrapValue * 1.5).toInt();
          }
        } 
        
        if ((age >= lifespan) || condition == ComponentCondition.damaged) {
          return scrapValue.toInt();
        }
        
        return 0;
      }
    
      void updateCondition(ComponentCondition partCondition) {
        condition = partCondition;
      }
    }
    
    void main(List<String> args) {
      ComponentModel engine = ComponentModel(componentPercent: 18, kerbWeight: 695, rate: 17, lifespan: 13, age: 2021);
      engine.updateCondition(ComponentCondition.good);
      final price = engine.calculatePrice();
      final price2 = engine.calculatePrice();
      print('price1 :$price');
      print('price2 : $price2');
    } 
    

    And now you get a glaring compiler error saying:

    Error: The setter 'age' isn't defined for the class 'ComponentModel'.

    • 'ComponentModel' is from 'package:dartpad_sample/main.dart' ('lib/main.dart'). age = DateTime.now().year - age; ^^^ Error: Compilation failed.

    This is great. The compiler just caught your error. You accidentially reassigned the age variable, instead of using a local variable, lets say something called "years". Maybe you should rename this.age to this.ModelMakeYear then your age local variable would be perfect.

    So with this changes, your code should look like this:

    enum ComponentCondition { missing, damaged, good }
    
    class ComponentModel {
      String? name;
      ComponentCondition condition = ComponentCondition.good;
    
      final double rate;
      final double componentPercent;
      final double kerbWeight;
      final int lifespan;
      final int modelMakeYear;
      
      ComponentModel(
          {this.name,
          required this.rate,
          required this.lifespan,
          required this.kerbWeight,
          required this.componentPercent,
          required this.modelMakeYear });
    
      int calculatePrice() {
        final weight = (componentPercent * kerbWeight) / 100;
        final double scrapValue = weight * rate;
        final i = lifespan ~/ 3;
        
        final age = DateTime.now().year - modelMakeYear;
    
        if ((condition == ComponentCondition.good || condition == ComponentCondition.damaged) && i == 0) {
          return scrapValue.toInt();
        }
        
        if (condition == ComponentCondition.good && age < lifespan) {
          if (age >= 0 && age <= i) {
            print('bestconditionPrice');
            return (scrapValue * 3).toInt();
          } 
          
          if (age > i && age <= i * 2) {
            return (scrapValue * 2).toInt();
          } 
          
          if (age > i * 2 && age < lifespan) {
            return (scrapValue * 1.5).toInt();
          }
        } 
        
        if ((age >= lifespan) || condition == ComponentCondition.damaged) {
          return scrapValue.toInt();
        }
        
        return 0;
      }
    
      void updateCondition(ComponentCondition partCondition) {
        condition = partCondition;
      }
    }
    
    void main(List<String> args) {
      final engine = ComponentModel(componentPercent: 18, kerbWeight: 695, rate: 17, lifespan: 13, modelMakeYear: 2021);
      engine.updateCondition(ComponentCondition.good);
      final price = engine.calculatePrice();
      final price2 = engine.calculatePrice();
      print('price1 :$price');
      print('price2 : $price2');
    }
    

    Works like a charm:

    bestconditionPrice bestconditionPrice price1 :6380 price2 : 6380

    The important part here is not the fish, but the fishing method: keep to all the best practices and let your compiler do the heavy lifting. It's a great tool, use it.