jeka 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/Gemfile +4 -0
  2. data/Gemfile.lock +55 -2
  3. data/README.rdoc +6 -14
  4. data/VERSION +1 -1
  5. data/bin/jeka +64 -94
  6. data/jeka.gemspec +56 -28
  7. data/lib/jeka.rb +6 -4
  8. data/lib/jeka/algorithm.rb +106 -24
  9. data/lib/jeka/analysis.rb +15 -0
  10. data/lib/jeka/analysis/algorithm.rb +13 -0
  11. data/lib/jeka/analysis/compiler.rb +14 -0
  12. data/lib/jeka/analysis/compiler_option.rb +24 -0
  13. data/lib/jeka/analysis/database.rb +11 -0
  14. data/lib/jeka/analysis/implementation.rb +15 -0
  15. data/lib/jeka/analysis/implementation_information.rb +24 -0
  16. data/lib/jeka/analysis/result.rb +20 -0
  17. data/lib/jeka/analysis/source_file.rb +24 -0
  18. data/lib/jeka/analysis/test.rb +15 -0
  19. data/lib/jeka/analysis/test_case.rb +13 -0
  20. data/lib/jeka/compilers.rb +3 -0
  21. data/lib/jeka/compilers/compiler.rb +48 -0
  22. data/lib/jeka/compilers/gpp.rb +29 -0
  23. data/lib/jeka/compilers/ruby.rb +21 -0
  24. data/lib/jeka/console.rb +55 -0
  25. data/lib/jeka/implementation.rb +22 -97
  26. data/lib/jeka/test.rb +15 -31
  27. data/lib/jeka/test_case.rb +41 -0
  28. data/test/bubble_sort/_tests/_test_01.rb +13 -0
  29. data/test/bubble_sort/algorithm_bubble_sort.rb +15 -0
  30. data/test/bubble_sort/cpp/_implementation.yaml +3 -0
  31. data/test/{example/01_bubble_sort/cpp/bubble.cpp → bubble_sort/cpp/bubble_sort.cpp} +9 -10
  32. data/test/bubble_sort/ruby/_implementation.yaml +3 -0
  33. data/test/{example/01_bubble_sort/ruby/bubble.rb → bubble_sort/ruby/bubble_sort.rb} +2 -5
  34. data/test/double/_tests/_test_01.rb +13 -0
  35. data/test/double/algorithm_double.rb +15 -0
  36. data/test/double/cpp/double.cpp +10 -0
  37. data/test/double/ruby/double.rb +2 -0
  38. data/test/test_algorithm.rb +25 -11
  39. data/test/test_gpp.rb +29 -0
  40. data/test/test_implementation.rb +25 -10
  41. data/test/test_test_case.rb +21 -0
  42. metadata +94 -52
  43. data/lib/jeka/jeka_helper.rb +0 -16
  44. data/lib/jeka/make.rb +0 -103
  45. data/test/example/01_bubble_sort/_algorithm.yaml +0 -12
  46. data/test/example/01_bubble_sort/_description.textile +0 -1
  47. data/test/example/01_bubble_sort/_references.textile +0 -1
  48. data/test/example/01_bubble_sort/_tests/test_01.yaml +0 -3
  49. data/test/example/01_bubble_sort/_tests/test_02.yaml +0 -3
  50. data/test/example/01_bubble_sort/cpp/_implementation.yaml +0 -9
  51. data/test/example/01_bubble_sort/ruby/_implementation.yaml +0 -6
  52. data/test/site/algorithm.textile +0 -27
  53. data/test/site/cpp.textile +0 -46
  54. data/test/site/ruby.textile +0 -28
  55. data/test/test_make.rb +0 -34
  56. data/test/test_test.rb +0 -16
data/lib/jeka.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  ROOT_PATH = File.expand_path(File.dirname(__FILE__))
2
2
 
3
- require File.join(ROOT_PATH, '/jeka/jeka_helper')
4
- require File.join(ROOT_PATH, '/jeka/algorithm')
5
- require File.join(ROOT_PATH, '/jeka/test')
3
+ require File.join(ROOT_PATH, '/jeka/compilers')
6
4
  require File.join(ROOT_PATH, '/jeka/implementation')
7
- require File.join(ROOT_PATH, '/jeka/make')
5
+ require File.join(ROOT_PATH, '/jeka/test')
6
+ require File.join(ROOT_PATH, '/jeka/algorithm')
7
+ require File.join(ROOT_PATH, '/jeka/test_case')
8
+ require File.join(ROOT_PATH, '/jeka/console')
9
+ require File.join(ROOT_PATH, '/jeka/analysis')
@@ -1,38 +1,120 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Jeka
4
+ class Algorithm
4
5
 
5
- class Algorithm < JekaHelper
6
+ attr_reader :database
6
7
 
7
- jeka_reader :name
8
- jeka_reader :type
9
- jeka_reader :complexity
10
- jeka_reader :description
11
- jeka_reader :references
8
+ def implementations
9
+ methods.select {|m| m =~ /^implementation_/}.map {|m| send(m)}
10
+ end
12
11
 
13
- def initialize(folder)
14
- super(File.join(folder, "_algorithm.yaml"))
15
- @implementations = nil
16
- @tests = nil
12
+ def self.implementation(name)
13
+ imp = Implementation.new(name)
14
+ yield imp
15
+ define_method("implementation_#{name}".to_sym) do
16
+ return imp
17
+ end
17
18
  end
18
19
 
19
- def tests
20
- return @tests = Test::test_set(File.join(@folder, "_tests")) unless @tests
21
- return @tests
20
+ def self.add_tests(test_dir)
21
+ Jeka::TestCase.reset
22
+ Dir.glob(test_dir).each do |d|
23
+ eval(File.open(d).readlines.join)
24
+ end
25
+ test_suites = Jeka::TestCase.test_suites
26
+
27
+ define_method(:test_suites) do
28
+ return test_suites
29
+ end
30
+
22
31
  end
23
32
 
24
- def implementations
25
- unless @implementations
26
- @implementations = []
27
- @jeka["implementations"].each do |i|
28
- imp = Implementation.new(File.join(@folder, i))
29
- imp.algorithm = self
30
- @implementations << imp
33
+ def jekafy
34
+ @database = Jeka::Analysis::Algorithm.create(
35
+ name: self.class.to_s,
36
+ implementations: implementations.collect {|imp| imp.jekafy},
37
+ test_cases: test_suites.collect {|tc| tc.jekafy}
38
+ )
39
+ end
40
+
41
+ def build(&block)
42
+ implementations.each do |imp|
43
+ b = imp.compiler.build
44
+ block.call(nil, :output, b[0]) if block_given?
45
+ block.call(nil, :error, b[1]) if block_given? and (not b[2] == 0)
46
+ end
47
+ end
48
+
49
+ def run(n=1, &block)
50
+ implementations.each do |imp|
51
+ test_suites.each do |ts|
52
+ ts.tests.each do |test|
53
+ n.times do
54
+ test_result = imp.compiler.run("#{test.input}\n")
55
+ block.call(nil, :output, test_result[0]) if block_given?
56
+ block.call(nil, :error, test_result[1]) if block_given? and (not test_result[2] == 0)
57
+ Jeka::Analysis::Result.create(
58
+ stdout: test_result[0].join,
59
+ stderr: test_result[1].join,
60
+ exit_status: test_result[2],
61
+ user_cpu_time: test_result[3][:user_cpu_time],
62
+ system_cpu_time: test_result[3][:system_cpu_time],
63
+ childrens_use_cpu_time: test_result[3][:childrens_use_cpu_time],
64
+ childrens_system_cpu_time: test_result[3][:childrens_system_cpu_time],
65
+ elapsed_real_time: test_result[3][:elapsed_real_time],
66
+ implementation: imp.database,
67
+ test: test.database
68
+ )
69
+ end
70
+ end
31
71
  end
32
72
  end
33
- return @implementations
34
73
  end
35
-
74
+
75
+ def self.reset
76
+ @@algorithms = {}
77
+ end
78
+
79
+ def self.inherited(klass)
80
+ @@algorithms ||= {}
81
+ @@algorithms[klass] = true
82
+ end
83
+
84
+ def self.algorithms
85
+ @@algorithms ||= {}
86
+ @@algorithms.keys.sort_by { |ts| ts.name }.collect{|ts| ts.new}
87
+ end
88
+
89
+ def self.build_all(&block)
90
+ block.call(0, :step, "Building algorithms...") if block_given?
91
+ n = self.algorithms.length + 1
92
+ i = 0
93
+ self.algorithms.each do |alg|
94
+ i += 1
95
+ block.call(100*i/n, :step, "Building #{alg.class.to_s}") if block_given?
96
+ block_given? ? alg.build(&block) : alg.build
97
+ end
98
+ block.call(100, :done, "Done") if block_given?
99
+ end
100
+
101
+ def self.run_all(n=1, &block)
102
+ Jeka::Analysis::Database.create(File.join(Dir.getwd, "analysis.jeka"))
103
+ block.call(0, :step, "Running algorithms...") if block_given?
104
+ s = self.algorithms.length + 1
105
+ i = 0
106
+ self.algorithms.each do |alg|
107
+ alg.jekafy
108
+ i += 1
109
+ block.call(100*i/s, :step, "Running #{alg.class.to_s}...") if block_given?
110
+ if block_given?
111
+ alg.run(n, &block)
112
+ else
113
+ alg.run(n)
114
+ end
115
+ end
116
+ block.call(100, :done, "Done") if block_given?
117
+ end
118
+
36
119
  end
37
-
38
- end
120
+ end
@@ -0,0 +1,15 @@
1
+ require 'rubygems'
2
+ require 'data_mapper'
3
+ require 'dm-migrations'
4
+
5
+
6
+ require File.join(ROOT_PATH, 'jeka/analysis/database')
7
+ require File.join(ROOT_PATH, 'jeka/analysis/algorithm')
8
+ require File.join(ROOT_PATH, 'jeka/analysis/implementation')
9
+ require File.join(ROOT_PATH, 'jeka/analysis/implementation_information')
10
+ require File.join(ROOT_PATH, 'jeka/analysis/compiler')
11
+ require File.join(ROOT_PATH, 'jeka/analysis/compiler_option')
12
+ require File.join(ROOT_PATH, 'jeka/analysis/source_file')
13
+ require File.join(ROOT_PATH, 'jeka/analysis/test')
14
+ require File.join(ROOT_PATH, 'jeka/analysis/test_case')
15
+ require File.join(ROOT_PATH, 'jeka/analysis/result')
@@ -0,0 +1,13 @@
1
+ module Jeka
2
+ module Analysis
3
+ class Algorithm
4
+ include DataMapper::Resource
5
+
6
+ property :id , Serial
7
+ property :name, String
8
+
9
+ has n, :implementations
10
+ has n, :test_cases
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Jeka
2
+ module Analysis
3
+ class Compiler
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+
9
+ belongs_to :implementation
10
+ has n, :compiler_options
11
+ has n, :source_files
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module Jeka
2
+ module Analysis
3
+ class CompilerOption
4
+ include DataMapper::Resource
5
+
6
+ property :id , Serial
7
+ property :name, String
8
+ property :value, String
9
+
10
+ belongs_to :compiler
11
+
12
+ def self.convert(hash)
13
+ opt = []
14
+ hash.each do |key, value|
15
+ opt << CompilerOption.new(
16
+ name: key,
17
+ value: value
18
+ )
19
+ end
20
+ opt
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module Jeka
2
+ module Analysis
3
+ class Database
4
+ def self.create(path)
5
+ DataMapper.finalize
6
+ DataMapper.setup(:default, "sqlite://#{path}")
7
+ DataMapper.auto_migrate!
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Jeka
2
+ module Analysis
3
+ class Implementation
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+
9
+ belongs_to :algorithm
10
+ has 1, :compiler
11
+ has n, :implementation_information
12
+ has n, :results
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ module Jeka
2
+ module Analysis
3
+ class ImplementationInformation
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+ property :value, String
9
+
10
+ belongs_to :implementation
11
+
12
+ def self.convert(hash)
13
+ info = []
14
+ hash.each do |key, value|
15
+ info << ImplementationInformation.new(
16
+ name: key,
17
+ value: value
18
+ )
19
+ end
20
+ info
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module Jeka
2
+ module Analysis
3
+ class Result
4
+ include DataMapper::Resource
5
+
6
+ property :id , Serial
7
+ property :stdout, String
8
+ property :stderr, String
9
+ property :exit_status, String
10
+ property :user_cpu_time, Float
11
+ property :system_cpu_time, Float
12
+ property :childrens_use_cpu_time, Float
13
+ property :childrens_system_cpu_time, Float
14
+ property :elapsed_real_time, Float
15
+
16
+ belongs_to :implementation
17
+ belongs_to :test
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module Jeka
2
+ module Analysis
3
+ class SourceFile
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+ property :source, Text
9
+
10
+ belongs_to :compiler
11
+
12
+ def self.convert(array)
13
+ files = []
14
+ array.each do |file|
15
+ files << SourceFile.new(
16
+ name: File.basename(file),
17
+ source: File.open(file).readlines.join
18
+ )
19
+ end
20
+ files
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ module Jeka
2
+ module Analysis
3
+ class Test
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+ property :output, String
9
+ property :input, String
10
+
11
+ belongs_to :test_case
12
+ has n, :results
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Jeka
2
+ module Analysis
3
+ class TestCase
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+
9
+ belongs_to :algorithm
10
+ has n, :tests
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ require File.join(ROOT_PATH, 'jeka/compilers/compiler')
2
+ require File.join(ROOT_PATH, 'jeka/compilers/gpp')
3
+ require File.join(ROOT_PATH, 'jeka/compilers/ruby')
@@ -0,0 +1,48 @@
1
+ require 'benchmark'
2
+ require 'open3'
3
+
4
+ module Jeka
5
+ module Compiler
6
+ class Compiler
7
+ attr_reader :database
8
+
9
+ def command(cmd)
10
+ stdout_ = nil
11
+ stderr_ = nil
12
+ exit_status_ = nil
13
+
14
+ b = Benchmark.measure do
15
+ Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
16
+ stdout_ = stdout.readlines
17
+ stderr_ = stderr.readlines
18
+ exit_status_ = wait_thr.value
19
+ end
20
+ end.to_a
21
+
22
+ bench = Hash.new
23
+ bench[:user_cpu_time] = b[1]
24
+ bench[:system_cpu_time] = b[2]
25
+ bench[:childrens_use_cpu_time] = b[3]
26
+ bench[:childrens_system_cpu_time] = b[4]
27
+ bench[:elapsed_real_time] = b[5]
28
+ return stdout_, stderr_, exit_status_.exitstatus, bench
29
+ end
30
+
31
+ def build(&block)
32
+ return _build_command ? command(_build_command) : [[], [], 0, 0]
33
+ end
34
+
35
+ def run(input = '')
36
+ return command("echo '#{input}' | #{_run_command}")
37
+ end
38
+
39
+ def jekafy
40
+ @database = Jeka::Analysis::Compiler.create(
41
+ name: self.class.to_s,
42
+ compiler_options: Jeka::Analysis::CompilerOption.convert(@options),
43
+ source_files: Jeka::Analysis::SourceFile.convert(@files)
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ module Jeka
2
+ module Compiler
3
+
4
+ class Gpp < Compiler
5
+ def initialize(files, options = {})
6
+ @files = files
7
+ @options = options
8
+ end
9
+
10
+ private
11
+
12
+ def _run_command
13
+ cmd = './' << @options[:o]
14
+ end
15
+
16
+ def _build_command
17
+ cmd = 'g++ '
18
+ @files.each do |f|
19
+ cmd << f << ' '
20
+ end
21
+ @options.each do |opt, value|
22
+ cmd << '-' << opt.to_s << ' ' << value
23
+ end
24
+ return cmd
25
+ end
26
+
27
+ end
28
+ end
29
+ end