Class: Polytrix::Challenge

Inherits:
Dash
  • Object
show all
Includes:
Polytrix::Core::FileSystemHelper, Documentation::Helpers::CodeHelper, Logging, StringHelpers
Defined in:
lib/polytrix/challenge.rb

Overview

rubocop:disable ClassLength

Defined Under Namespace

Classes: FSM

Instance Method Summary collapse

Methods included from Documentation::Helpers::CodeHelper

#code_block, #initialize, #snippet_after, #snippet_between, #source

Methods included from StringHelpers

included

Methods included from StringHelpers::ClassMethods

#slugify

Methods included from Polytrix::Core::FileSystemHelper

#find_file, #recursive_parent_search

Methods inherited from Dash

#initialize

Instance Method Details

#absolute_source_fileObject



44
45
46
47
48
# File 'lib/polytrix/challenge.rb', line 44

def absolute_source_file
  return nil if source_file.nil?

  File.expand_path source_file, basedir
end

#action(what, &block) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/polytrix/challenge.rb', line 135

def action(what, &block)
  @state = state_file.read
  elapsed = Benchmark.measure do
    # synchronize_or_call(what, @state, &block)
    block.call(@state)
  end
  @state['last_action'] = what.to_s
  elapsed
rescue Polytrix::FeatureNotImplementedError => e
  raise e
rescue ActionFailed => e
  log_failure(what, e)
  fail(ChallengeFailure, failure_message(what) +
    "  Please see .polytrix/logs/#{name}.log for more details",
       e.backtrace)
rescue Exception => e # rubocop:disable RescueException
  log_failure(what, e)
  fail ActionFailed,
       "Failed to complete ##{what} action: [#{e.message}]", e.backtrace
ensure
  state_file.write(@state) unless what == :destroy
end

#code2docObject



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/polytrix/challenge.rb', line 85

def code2doc
  if source_file.nil?
    warn "No code sample available for #{slug}, no documentation will be generated."
    return
  end

  display_file = relativize(absolute_source_file, Dir.pwd)
  banner "Generating documentation for #{slug} from #{display_file}"
  target_dir = Polytrix.configuration.documentation_dir
  format = Polytrix.configuration.documentation_format
  target_file_name = File.basename(source_file, File.extname(source_file)) + ".#{format}"
  target_file = File.join(target_dir, target_file_name)
  doc = Polytrix::DocumentationGenerator.new.code2doc(absolute_source_file)
  FileUtils.mkdir_p File.dirname(target_file)
  File.write(target_file, doc)
  info "Documentated saved to #{target_file}"
rescue Polytrix::Documentation::CommentStyles::UnknownStyleError => e
  abort "Unknown file extension: #{e.extension}, please use --lang to set the language manually"
end

#destroyObject



67
68
69
# File 'lib/polytrix/challenge.rb', line 67

def destroy
  transition_to :destroy
end

#destroy_actionObject



105
106
107
108
109
110
111
112
# File 'lib/polytrix/challenge.rb', line 105

def destroy_action
  perform_action(:destroy, 'Destroying') do
    @state_file.destroy
    @state_file = nil
    @validations = nil
    @state = {}
  end
end

#execObject



50
51
52
# File 'lib/polytrix/challenge.rb', line 50

def exec
  transition_to :exec
end

#exec_actionObject



54
55
56
57
58
59
60
61
# File 'lib/polytrix/challenge.rb', line 54

def exec_action
  perform_action(:exec, 'Executing') do
    fail FeatureNotImplementedError, "Implementor #{name} has not been cloned" unless implementor.cloned?
    fail FeatureNotImplementedError, name if source_file.nil?
    fail FeatureNotImplementedError, name unless File.exists?(absolute_source_file)
    self.result = challenge_runner.run_challenge self
  end
end

#failure_message(what) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a string explaining what action failed, at a high level. Used for displaying to end user.

Parameters:

  • what (String)

    an action

Returns:

  • (String)

    a failure message



197
198
199
# File 'lib/polytrix/challenge.rb', line 197

def failure_message(what)
  "#{what.capitalize} failed on instance #{slug}."
end

#last_actionString

Returns the last successfully completed action state of the instance.

Returns:

  • (String)

    a named action which was last successfully completed



161
162
163
# File 'lib/polytrix/challenge.rb', line 161

def last_action
  state_file.read['last_action']
end

#log_failure(what, e) ⇒ Object



184
185
186
187
188
189
# File 'lib/polytrix/challenge.rb', line 184

def log_failure(what, e)
  return if logger.logdev.nil?

  logger.logdev.error(failure_message(what))
  # Error.formatted_trace(e).each { |line| logger.logdev.error(line) }
end

#loggerObject



36
37
38
# File 'lib/polytrix/challenge.rb', line 36

def logger
  implementor.logger
end

#perform_action(verb, output_verb) ⇒ Object



125
126
127
128
129
130
131
132
133
# File 'lib/polytrix/challenge.rb', line 125

def perform_action(verb, output_verb)
  banner "#{output_verb} #{slug}..."
  elapsed = action(verb) { yield }
  # elapsed = action(verb) { |state| driver.public_send(verb, state) }
  info("Finished #{output_verb.downcase} #{slug}" \
    " #{Util.duration(elapsed.real)}.")
  # yield if block_given?
  self
end

#slugObject



40
41
42
# File 'lib/polytrix/challenge.rb', line 40

def slug
  slugify("#{suite}-#{name}-#{implementor.name}")
end

#state_fileObject



32
33
34
# File 'lib/polytrix/challenge.rb', line 32

def state_file
  @state_file ||= StateFile.new(Dir.pwd, slug)
end

#test(destroy_mode = :passing) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/polytrix/challenge.rb', line 71

def test(destroy_mode = :passing)
  elapsed = Benchmark.measure do
    banner "Cleaning up any prior instances of #{slug}"
    destroy
    banner "Testing #{slug}"
    verify
    # destroy if destroy_mode == :passing
  end
  info "Finished testing #{slug} #{Util.duration(elapsed.real)}."
  self
# ensure
  # destroy if destroy_mode == :always
end

#transition_to(desired) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/polytrix/challenge.rb', line 169

def transition_to(desired)
  transition_result = nil
  begin
    FSM.actions(last_action, desired).each do |transition|
      transition_result = send("#{transition}_action")
    end
  rescue Polytrix::FeatureNotImplementedError
    warn("#{slug} is not implemented")
  rescue ActionFailed => e
    error("#{slug} failed: #{e}")
    fail(ChallengeFailure, e.message, e.backtrace)
  end
  transition_result
end

#validationsObject



165
166
167
# File 'lib/polytrix/challenge.rb', line 165

def validations
  @validations ||= (state_file.read['validations'] || [])
end

#verifyObject



63
64
65
# File 'lib/polytrix/challenge.rb', line 63

def verify
  transition_to :verify
end

#verify_actionObject



114
115
116
117
118
119
120
121
122
123
# File 'lib/polytrix/challenge.rb', line 114

def verify_action
  perform_action(:verify, 'Verifying') do
    validators = Polytrix::ValidatorRegistry.validators_for self
    validators.each do |validator|
      validator.validate(self)
      validations << validator.description
    end
    @state['validations'] = validations
  end
end