Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Magic in Fitnext

Magic in Fitnext

the core algorithm of generating meals for fitness

Jimmy Huang

August 21, 2015
Tweet

More Decks by Jimmy Huang

Other Decks in Programming

Transcript

  1. Magic in Fitnext
    — “engine, start”

    View full-size slide

  2. ? ?
    ?
    ?
    ?
    Where is the magic?

    View full-size slide

  3. Ingredient Rules
    User’s program and diagnosis
    Food constraints

    View full-size slide

  4. Food Constraints

    View full-size slide

  5. • “detox = yes”
    • “cycle_index is odd”
    • “moment is breakfast”
    • “day_index included_in 1,3”
    Raw materials

    View full-size slide

  6. Steps
    1. Manufacture (mapping, translate)
    2. Dynamic evaluation

    View full-size slide

  7. Manufacture
    #
    #
    operator = (matcher.nil? || matcher.eql?('=') || ['odd', 'even'].include?
    (matcher)) ? '==' : matcher
    key = case attr
    when 'detox': 'has_detox_readiness'
    when 'objective': 'objective_id'
    when 'cycle_index'
    ['odd', 'even'].include?(matcher) ? 'cycle_parity' : 'cycle_number'
    else
    attr
    end
    val = ['odd', 'even'].include?(matcher) ? "\'#{matcher}'" : value

    View full-size slide

  8. #
    "#{key} #{operator} #{val}"
    "has_detox_readiness == true"
    #
    "cycle_parity == 'odd'"

    View full-size slide

  9. The object
    object = attr.eql?('sport_sessions_per_week') ? diagnosis : diagnosis.program
    #nil, started: nil, has_detox_readiness: true,…>
    # program.rb
    def cycle_number
    user.program_histories.count + 1
    end
    def cycle_parity
    (cycle_number % 2) == 0 ? 'even' : 'odd'
    end

    View full-size slide

  10. Dynamic evaluation
    object.send(:eval, "#{key} #{operator} #{val}")
    — Code is data, data is code
    It is important for one to think of code as data to understand what eval is all about.
    The idea is that the code itself can be manifested as a primitive data type which the
    language can then make sense of.
    program.has_detox_readiness == true
    program.cycle_parity == 'odd'
    Kernel.eval()

    View full-size slide

  11. eval() can be evil
    eval(“program.has_detox_readiness == User.delete_all”)
    Check and validate the user input!

    View full-size slide

  12. constraint 1
    constraint 2
    constraint 3
    constraint 4

    View full-size slide

  13. Ingredient rules

    View full-size slide

  14. # Diagnosis.rb
    include InferenceEngine::Inputs
    diagnosis.respond_to(“season_january”) == true

    View full-size slide

  15. module InferenceEngine
    module Rule
    def evaluate(input_object)
    @evaluation_result = false
    if input_object.respond_to?(self.attribute_name)
    @evaluation_result = (input_object.send(self.attribute_name) ==
    (self.value == 1))
    else
    false
    end
    end
    end
    end
    # ingredient.rb
    include InferenceEngine::Inference
    # ingredient_rule.rb
    include InferenceEngine::Rule

    View full-size slide

  16. module InferenceEngine
    module Inference
    def infere!(input_object)
    @excluded = false
    @priority_level = 0
    @evaluated_rules = []
    rules.each do |rule|
    @evaluated_rules << rule
    if rule.evaluate(input_object)
    case rule.human_rule_type
    when :exclude
    @excluded = true
    return
    when :prioritize
    @priority_level += 1
    when :penalize
    @priority_level -= 1
    end
    end
    end
    end

    View full-size slide

  17. constraint 3

    View full-size slide