Guest User

Untitled

a guest
Jan 22nd, 2018
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.90 KB | None | 0 0
  1. class Symbol
  2. def / sym
  3. :"#{self}/#{sym}"
  4. end
  5.  
  6. def ~
  7. Checklist.lists[self].start
  8. end
  9. end
  10.  
  11. module Checklist
  12.  
  13. class << self; attr_accessor :lists; end
  14.  
  15. def checklist label=nil, description=nil, &block
  16. label ||= "list-#{Time.now.to_i}-#{rand 1000}"
  17. Checklist.lists ||= {}
  18. Checklist.lists[label] = List.new label, description, &block
  19. end
  20.  
  21.  
  22. class List
  23.  
  24. attr_accessor :current, :score_override, :total_override
  25. attr_reader :checks
  26.  
  27. def initialize label, description=nil, &block
  28. @label = label
  29. @description = description
  30. @checks = []
  31. instance_eval &block
  32. end
  33.  
  34. def check description=nil, options={}, &block
  35. options[:checklist] ||= self
  36. @checks << Check.new(description, options, &block)
  37. end
  38.  
  39. def previous
  40. @current > 0 ? @checks[@current-1].run : @checks[@current].run
  41. end
  42.  
  43. def next
  44. available = @current+1 <= @checks.size-1
  45. if available then
  46. @checks[@current+1].run
  47. else
  48. @checks[@current].answer ? finish : @checks[@current].run
  49. end
  50. end
  51.  
  52. def start
  53. @checks.first.run
  54. end
  55.  
  56. def finish
  57. report
  58. exit
  59. end
  60.  
  61. def report
  62. puts
  63. puts "="*50
  64. @checks.each_with_index do |check, i|
  65. puts "Check\t##{i+1}: #{check.score}/#{check.total}"
  66. end
  67. puts "-"*50
  68. puts "Score: #{score}/#{total}"
  69. puts "="*50
  70. end
  71.  
  72. def score
  73. @checks.map{|c| c.score}.reduce :"+"
  74. end
  75.  
  76. def total
  77. @checks.map{|c| c.total}.reduce :"+"
  78. end
  79.  
  80.  
  81. end
  82.  
  83. class Check
  84.  
  85. attr_reader :answer, :score
  86.  
  87. def initialize description=nil, options={}, &block
  88. @description = description
  89. @options = options
  90. @options[:value] ||= 1
  91. @options[:mandatory] ||= false
  92. @score = 0
  93. instance_eval &block if block_given?
  94. raise RuntimeError, "Task #{@options[:label]} is not assigned to any checklist" unless @options[:checklist]
  95. raise RuntimeError, "No description provided for task #{@options[:label]}" unless @description
  96. [:value, :label, :mandatory, :checklist].each do |v|
  97. var = :"@#{v}"
  98. instance_variable_set var, @options[v] unless instance_variable_get var
  99. end
  100. end
  101.  
  102. def total
  103. if @choices then
  104. @choices.map{|c| c[:value]}.max
  105. else
  106. @value
  107. end
  108. end
  109.  
  110. def description text
  111. @description = text
  112. end
  113.  
  114. def mandatory
  115. @mandatory = true
  116. end
  117.  
  118. def beforehand &block
  119. @beforehand = block
  120. end
  121.  
  122. def afterwards &block
  123. @afterwards = block
  124. end
  125.  
  126. def value n
  127. @value = n
  128. end
  129.  
  130. def choice description, value=1
  131. @choices ||= []
  132. @choices << {description: description, value: value}
  133. end
  134.  
  135. def run
  136. @checklist.current = @checklist.checks.index self
  137. instance_eval &@beforehand if @beforehand
  138. loop do
  139. puts "="*50
  140. puts "Check #{@checklist.current+1}/#{@checklist.checks.size} (Score: #{@checklist.score}/#{@checklist.total})"
  141. puts "-"*50
  142. describe
  143. break if (@choices ? choose : confirm)
  144. end
  145. instance_eval &@afterwards if @afterwards
  146. @checklist.next
  147. end
  148.  
  149. protected
  150.  
  151. def describe
  152. print @description
  153. end
  154.  
  155. def choose
  156. print "\n"
  157. @choices.each_with_index do |choice, i|
  158. puts "-- #{i+1}. #{choice[:description]}"
  159. end
  160. @answer = input do |answer|
  161. sel = answer.to_i
  162. sel > 0 && sel <= @choices.size
  163. end
  164. @score = @choices[@answer.to_i-1][:value] if @answer
  165. end
  166.  
  167. def confirm
  168. print " [y/n]\n"
  169. @answer = input do |answer|
  170. answer =~ /^(y(es)?|n(o)?)$/i
  171. end
  172. if @answer then
  173. @score = @answer =~ /^y(es)?$/i ? @value : 0
  174. end
  175. end
  176.  
  177. def finish
  178. @checklist.finish
  179. end
  180.  
  181. def separate
  182. puts '='*50
  183. end
  184.  
  185. def input(message="=> Error: Invalid answer.", prompt='~> ', &block)
  186. puts "~"*50
  187. print prompt
  188. answer = gets.chomp
  189. case answer
  190. when '<' then
  191. @checklist.previous
  192. return
  193. when '>' then
  194. if @mandatory then
  195. message = "=> Error: check cannot be skipped."
  196. else
  197. @checklist.next
  198. return
  199. end
  200. when '<<' then
  201. @checklist.start
  202. return
  203. when '>>' then
  204. @checklist.finish
  205. end
  206. valid = block.call(answer)
  207. if valid then
  208. answer
  209. else
  210. puts message
  211. false
  212. end
  213. end
  214.  
  215. end
  216.  
  217.  
  218. end
  219.  
  220.  
  221. ###########################
  222.  
  223. include Checklist
  224.  
  225. checklist :test/:checklist do
  226.  
  227. check "Ready?"
  228.  
  229. check do
  230. description "Choose something"
  231. mandatory
  232. choice "Do this"
  233. choice "Do that", 0
  234. choice "None of the above", 2
  235. afterwards do
  236. if @score > 1 then
  237. finish
  238. end
  239. end
  240. end
  241.  
  242. check do
  243. description "Do something else?"
  244. value 3
  245. end
  246.  
  247. check "OK?", value: 10, mandatory: true
  248.  
  249. end
  250.  
  251. ~(:test/:checklist)
Add Comment
Please, Sign In to add comment