jeka 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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