nem_test_vectors.rb 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #!/usr/bin/env ruby
  2. require 'highline'
  3. require 'open-uri'
  4. TEMPLATE_NAME = (Pathname.new(__FILE__).sub_ext '.erb').to_s.freeze
  5. @terminal = HighLine.new($stdin, $stderr)
  6. def github_files
  7. require 'octokit'
  8. @github_files ||= Octokit.contents('NemProject/nem-test-vectors')
  9. .select do |file|
  10. file.name.end_with? '.dat'
  11. end
  12. end
  13. def choose_data_file
  14. @terminal.choose do |menu|
  15. github_files.each do |file|
  16. menu.choice(file.name) { file.download_url }
  17. end
  18. menu.prompt = 'Which file? '
  19. menu.index = :none
  20. menu.select_by = :name
  21. end
  22. end
  23. def load_header(line)
  24. line = line.dup
  25. abort 'Header is not a comment' unless line.slice!(0) == '#'
  26. header = line.split(':').each(&:strip!)
  27. header.shift if header.first.empty?
  28. header
  29. end
  30. def parse_field_answer(answer)
  31. if answer.empty?
  32. nil
  33. elsif /^(?:(?<type>\w+) )?(?<identifier>\w+)$/ =~ answer
  34. [identifier, type]
  35. else
  36. raise NotValidQuestionError
  37. end
  38. end
  39. def ask_fields(header)
  40. header.map do |name|
  41. @terminal.ask "Field for `#{name}'? " do |question|
  42. question.answer_type = lambda(&method(:parse_field_answer))
  43. end
  44. end
  45. end
  46. def load_data_line(line)
  47. abort 'Line does not begin with colon' unless line.slice!(0) == ':'
  48. line.strip!
  49. line.chomp!(',')
  50. values = line.split(':').each(&:strip!)
  51. values.pop if values.last.empty?
  52. values
  53. end
  54. def load_data(file, count)
  55. file.each_line.lazy.reject { |line| line.start_with? '#' }
  56. .take(count)
  57. .map(&method(:load_data_line))
  58. .to_a
  59. end
  60. def remove_skipped_fields(fields, data)
  61. data.each do |values|
  62. abort 'Line does not match header' unless values.size == fields.size
  63. values.reject!.each_with_index { |_, index| fields[index].nil? }
  64. end
  65. fields.compact!
  66. end
  67. def format_data_fields(fields, data)
  68. data.each do |values|
  69. fields.each_with_index do |(_, type), index|
  70. values[index] = values[index].dump if type.nil?
  71. end
  72. end
  73. end
  74. def template(source_url, fields, data)
  75. test_name = @terminal.ask('Name for test? ') do |question|
  76. question.validate = /./
  77. end
  78. erb = ERB.new(File.read(TEMPLATE_NAME), nil, '-')
  79. erb.filename = TEMPLATE_NAME
  80. erb.result(binding)
  81. end
  82. download_url = choose_data_file
  83. source_code = open download_url do |file|
  84. line = file.readline
  85. header = load_header(line)
  86. @terminal.say line
  87. count = @terminal.ask('How many vectors to import? ', Integer)
  88. fields = ask_fields(header)
  89. data = load_data(file, count)
  90. remove_skipped_fields(fields, data)
  91. format_data_fields(fields, data)
  92. template(download_url, fields, data)
  93. end
  94. puts source_code