You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: compute.rb
    path of file: ./repos/ekylibre/app/services/interventions/computation
    
    the code of the file until where you have to start completion: # frozen_string_literal: true

# Permits to compute Intervention from a small set of parameters
module Interventions
  module Computation
    class Compute
      attr_reader :intervention

      def initialize(parameters: {})
        @parameters = parameters
      end

      def perform(options: {})
        compute(@parameters.merge(options))
      end

      private

        def compute(attributes)
          # Extract readings from the attributes since procedo doesn't create readings when initialized
          readings = ExtractReadings.new(attributes).perform

          @parameters = AddNecessaryAttributes.new(@parameters).perform

          # Convert set of attributes from an array of hash to a hash with index
          attrs = ComputedParameters.new(@parameters.deep_dup).perform.to_unsafe_h

          # Convert set of attributes from an array of hash to a hash with index in order to make Procedo to handle them (exclude nested_attributes marked for destruction)
          procedo_attrs = ProcedoComputedParameters.new(@parameters.deep_dup).perform.to_unsafe_h

          # Convert set of attributes from an array of hash to a hash with index in order to make Procedo to handle them
          engine_intervention = Procedo::Engine.new_intervention(procedo_attrs)
          # Iterate over engine_intervention parameters in order to add reading to parameter which depend on it for calculation
          ComputeReadings.new(engine_intervention).perform

          begin
            # Enables to add the custom reading passed on the API payload and extracted before creating the procedo intervention
            AddCustomRead
    
        def compute(attributes)
          # Extract readings from the attributes since procedo doesn't create readings when initialized
          readings = ExtractReadings.new(attributes).perform

          @parameters = AddNecessaryAttributes.new(@parameters).perform

          # Convert set of attributes from an array of hash to a hash with index
          attrs = ComputedParameters.new(@parameters.deep_dup).perform.to_unsafe_h

          # Convert set of attributes from an array of hash to a hash with index in order to make Procedo to handle them (exclude nested_attributes marked for destruction)
          procedo_attrs = ProcedoComputedParameters.new(@parameters.deep_dup).perform.to_unsafe_h

          # Convert set of attributes from an array of hash to a hash with index in order to make Procedo to handle them
          engine_intervention = Procedo::Engine.new_intervention(procedo_attrs)
          # Iterate over engine_intervention parameters in order to add reading to parameter which depend on it for calculation
          ComputeReadings.new(engine_intervention).perform

          begin
            # Enables to add the custom reading passed on the API payload and extracted before creating the procedo intervention
            AddCustomReadings.new(engine_intervention, readings).perform if readings.any?

            # Build 'html' selector which enables to recognize which part of the attributes needs to be updated
            UpdateEngineIntervention.new(engine_intervention, procedo_attrs).perform

            attributes = attributes.merge(attrs).to_unsafe_h.deep_merge(engine_intervention.to_attributes)
          ensure
            # Readings added on references needs to be removed after merging attributes in order for the visual interface not to display additional fields
            RemoveCustomProcedureReadings.new(engine_intervention).perform if readings.any?
          end

          attributes
        end