foodAX 3.3.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.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +12 -0
- data/.travis.yml +6 -0
- data/Gemfile +6 -0
- data/Guardfile +82 -0
- data/LICENSE.txt +21 -0
- data/README.md +70 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docs/DLLModule.html +126 -0
- data/docs/DLLModule/DLL.html +1185 -0
- data/docs/DLLModule/Node.html +409 -0
- data/docs/Food.html +567 -0
- data/docs/FoodAbstract.html +807 -0
- data/docs/FoodGem.html +156 -0
- data/docs/_config.yml +1 -0
- data/docs/_index.html +154 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +492 -0
- data/docs/file.README.html +161 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +161 -0
- data/docs/input/dish_recipes.txt +18 -0
- data/docs/input/food-data.txt +19 -0
- data/docs/input/samples-data.txt +9 -0
- data/docs/js/app.js +248 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +267 -0
- data/docs/top-level-namespace.html +297 -0
- data/food.gemspec +45 -0
- data/input/dish_recipes.txt +18 -0
- data/input/food-data.txt +19 -0
- data/input/samples-data.txt +9 -0
- data/lib/dsl/harvard_dish.rb +123 -0
- data/lib/food.rb +12 -0
- data/lib/food/dll.rb +168 -0
- data/lib/food/food_class.rb +139 -0
- data/lib/food/functions.rb +144 -0
- data/lib/food/sort.rb +135 -0
- data/lib/food/version.rb +6 -0
- metadata +216 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
# USEFUL FUNCTIONS
|
2
|
+
|
3
|
+
def read_recipe (recipe_filename)
|
4
|
+
recipes = File.open(recipe_filename).read.split("\n") # Divido el fichero en string de lineas
|
5
|
+
# hash nombre_receta ingredientes(proc)
|
6
|
+
recipe_ingredient_hash = Hash.new()
|
7
|
+
|
8
|
+
# Por cada receta ( Que tenga un { )
|
9
|
+
recipes.grep(/{/).each { |recipe_title|
|
10
|
+
|
11
|
+
# Coger el índice donde empieza y donde termina (Que tenga un })
|
12
|
+
start_index = recipes.find_index{ |line| line == recipe_title }
|
13
|
+
end_index = recipes[start_index..-1].find_index{ |line| line == "}" }
|
14
|
+
|
15
|
+
# Cogemos lo que está dentro de los dos índices (la receta)
|
16
|
+
|
17
|
+
recipe_ingredient_hash[recipe_title[0..-3]] = recipes[start_index+1, end_index-1]
|
18
|
+
# .join("\n")
|
19
|
+
}
|
20
|
+
|
21
|
+
return recipe_ingredient_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def read_samples_data (samples_data_filename)
|
25
|
+
data_file = File.open(samples_data_filename)
|
26
|
+
data_file = data_file.read.split("\n")[1..-1] # Divido el fichero en líneas y quito la primera
|
27
|
+
data_line_array = data_file.collect! { |data_array| data_array.split(" ") } # Cambio las líneas a arrays
|
28
|
+
|
29
|
+
# Hash with (name of the food, sample array for all the persons to that foods)
|
30
|
+
sample_people_hash = Hash.new([])
|
31
|
+
person_number = 1
|
32
|
+
line_counter = 0
|
33
|
+
|
34
|
+
# Mientras no hayamos recorrido todas las lineas y el primero sea un int (nuevo individuo)
|
35
|
+
while ((line_counter < data_line_array.count) && (data_line_array[line_counter][0].to_i == person_number))
|
36
|
+
|
37
|
+
data_line = data_line_array[line_counter]
|
38
|
+
|
39
|
+
person_number = person_number + 1 # Change of person
|
40
|
+
data_line = data_line[1..-1] # Delete the person number
|
41
|
+
|
42
|
+
while ((line_counter < data_line_array.count) && (data_line_array[line_counter][0].to_i != person_number))
|
43
|
+
food_name = data_line[0].capitalize
|
44
|
+
sample_person_array = data_line[1..-1].collect { |data| data.to_f } # Cambio numeros a float
|
45
|
+
|
46
|
+
if (sample_people_hash[food_name] == [])
|
47
|
+
if (food_name == "Glucosa")
|
48
|
+
sample_people_hash.each_key { |name| sample_people_hash[name][person_number-2].push(sample_person_array) }
|
49
|
+
else
|
50
|
+
sample_people_hash[food_name] = [[sample_person_array]]
|
51
|
+
end
|
52
|
+
else
|
53
|
+
sample_people_hash[food_name].push([sample_person_array])
|
54
|
+
end
|
55
|
+
|
56
|
+
line_counter = line_counter + 1 # Cambio de línea
|
57
|
+
unless (line_counter >= data_line_array.count)
|
58
|
+
data_line = data_line_array[line_counter]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
#sample_people_hash.each{ |x, y| puts "#{x} => #{y}" }
|
64
|
+
|
65
|
+
return sample_people_hash
|
66
|
+
end
|
67
|
+
|
68
|
+
# Method to read data by file
|
69
|
+
# @params data_filename [String] filename of the data
|
70
|
+
# @return [Array] Return array of food
|
71
|
+
def read_data (data_filename, samples_data_filename = "")
|
72
|
+
data_string = File.open(data_filename).read.split("\n") # Divido el fichero en string de lineas
|
73
|
+
food_array = []
|
74
|
+
|
75
|
+
if (samples_data_filename != "")
|
76
|
+
sample_people_hash = read_samples_data(samples_data_filename)
|
77
|
+
end
|
78
|
+
|
79
|
+
data_string.each { |data_line|
|
80
|
+
data_line = data_line.split(" ") # La divido en espacios
|
81
|
+
name = ""
|
82
|
+
|
83
|
+
while (data_line[0] != data_line[0].to_f.to_s) # Si el nombre no cambia al pasar de string afloat es que es un float
|
84
|
+
name << data_line[0] << " "
|
85
|
+
data_line = data_line[1..-1] # Quito el primer elemento
|
86
|
+
end
|
87
|
+
|
88
|
+
food_name = name[0..-2].capitalize
|
89
|
+
protein = [data_line[0].to_f, PROTEIN_ENERGY]
|
90
|
+
glucid = [data_line[1].to_f, GLUCID_ENERGY]
|
91
|
+
lipid = [data_line[2].to_f, LIPID_ENERGY]
|
92
|
+
|
93
|
+
data_line = data_line[3..-1]
|
94
|
+
|
95
|
+
|
96
|
+
group_name = ""
|
97
|
+
while (!data_line[0].nil?) # Si el nombre no cambia al pasar de string afloat es que es un float
|
98
|
+
group_name << data_line[0] << " "
|
99
|
+
data_line = data_line[1..-1] # Quito el primer elemento
|
100
|
+
end
|
101
|
+
|
102
|
+
if (samples_data_filename != "")
|
103
|
+
food = Food.new(food_name, protein, glucid, lipid, group_name[0..-2], sample_people_hash[food_name])
|
104
|
+
else
|
105
|
+
food = Food.new(food_name, protein, glucid, lipid, group_name[0..-2])
|
106
|
+
end
|
107
|
+
|
108
|
+
food_array.push(food)
|
109
|
+
}
|
110
|
+
|
111
|
+
return food_array
|
112
|
+
end
|
113
|
+
|
114
|
+
def read_ingredient_database(data_filename)
|
115
|
+
data_string = File.open(data_filename).read.split("\n") # Divido el fichero en string de lineas
|
116
|
+
food_hash = Hash.new()
|
117
|
+
|
118
|
+
data_string.each { |data_line|
|
119
|
+
data_line = data_line.split(" ") # La divido en espacios
|
120
|
+
name = ""
|
121
|
+
|
122
|
+
while (data_line[0] != data_line[0].to_f.to_s) # Si el nombre no cambia al pasar de string afloat es que es un float
|
123
|
+
name << data_line[0] << " "
|
124
|
+
data_line = data_line[1..-1] # Quito el primer elemento
|
125
|
+
end
|
126
|
+
|
127
|
+
food_name = name[0..-2].capitalize
|
128
|
+
protein = [data_line[0].to_f, PROTEIN_ENERGY]
|
129
|
+
glucid = [data_line[1].to_f, GLUCID_ENERGY]
|
130
|
+
lipid = [data_line[2].to_f, LIPID_ENERGY]
|
131
|
+
|
132
|
+
data_line = data_line[3..-1]
|
133
|
+
|
134
|
+
group_name = ""
|
135
|
+
while (!data_line[0].nil?)
|
136
|
+
group_name << data_line[0] << " "
|
137
|
+
data_line = data_line[1..-1] # Quito el primer elemento
|
138
|
+
end
|
139
|
+
|
140
|
+
food_hash[food_name] = Food.new(food_name, protein, glucid, lipid, group_name[0..-2])
|
141
|
+
}
|
142
|
+
|
143
|
+
return food_hash
|
144
|
+
end
|
data/lib/food/sort.rb
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
# Swap changes elements in position!
|
4
|
+
def swap(i, j)
|
5
|
+
clone_array = self.clone
|
6
|
+
clone_array[i], clone_array[j] = clone_array[j], clone_array[i]
|
7
|
+
clone_array
|
8
|
+
end
|
9
|
+
|
10
|
+
def swap!(i, j)
|
11
|
+
self[i], self[j] = self[j], self[i]
|
12
|
+
end
|
13
|
+
|
14
|
+
def bubble_sort_imp()
|
15
|
+
clone_array = self.clone
|
16
|
+
|
17
|
+
for i in 1...clone_array.size
|
18
|
+
for j in 0...(clone_array.size - i)
|
19
|
+
clone_array.swap!(j, j+1) if (clone_array[j] > clone_array[j+1])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
clone_array
|
24
|
+
end
|
25
|
+
|
26
|
+
def bubble_sort_imp!()
|
27
|
+
self.replace(self.bubble_sort_imp())
|
28
|
+
end
|
29
|
+
|
30
|
+
def bubble_sort()
|
31
|
+
clone_array = self.clone
|
32
|
+
|
33
|
+
(1...clone_array.size).each { |i|
|
34
|
+
(0...(clone_array.size - i)).each { |j|
|
35
|
+
clone_array.swap!(j, j+1) if (clone_array[j] > clone_array[j+1])
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
clone_array
|
40
|
+
end
|
41
|
+
|
42
|
+
def bubble_sort!()
|
43
|
+
self.replace(self.bubble_sort())
|
44
|
+
end
|
45
|
+
|
46
|
+
def merge_sort()
|
47
|
+
split_array(self)
|
48
|
+
end
|
49
|
+
|
50
|
+
def merge_sort_imp()
|
51
|
+
split_array(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def split_array_imp(sorted_array)
|
57
|
+
if (sorted_array.size <= 2)
|
58
|
+
if ((sorted_array.size == 2) && (sorted_array[0] > sorted_array[1]))
|
59
|
+
return sorted_array.swap(0, 1)
|
60
|
+
else
|
61
|
+
return sorted_array
|
62
|
+
end
|
63
|
+
else
|
64
|
+
middle = sorted_array.size / 2
|
65
|
+
array_1 = split_array(sorted_array[0...middle])
|
66
|
+
array_2 = split_array(sorted_array[middle...sorted_array.size])
|
67
|
+
|
68
|
+
return merge_arrays(array_1, array_2)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def merge_arrays_imp(array_1, array_2)
|
73
|
+
sorted_array = Array.new()
|
74
|
+
|
75
|
+
i = 0 # Iterador array_1
|
76
|
+
j = 0 # Iterador array_2
|
77
|
+
|
78
|
+
while ((i < array_1.size) && (j < array_2.size)) # Iterador array_3
|
79
|
+
if (array_1[i] <= array_2[j])
|
80
|
+
sorted_array.push(array_1[i])
|
81
|
+
i = i+1
|
82
|
+
else
|
83
|
+
sorted_array.push(array_2[j])
|
84
|
+
j = j+1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
while(i < array_1.size)
|
89
|
+
sorted_array.push(array_1[i])
|
90
|
+
i = i+1
|
91
|
+
end
|
92
|
+
|
93
|
+
while(j < array_2.size)
|
94
|
+
sorted_array.push(array_2[j])
|
95
|
+
j = j+1
|
96
|
+
end
|
97
|
+
|
98
|
+
return sorted_array
|
99
|
+
end
|
100
|
+
|
101
|
+
def split_array(sorted_array)
|
102
|
+
if (sorted_array.size <= 2)
|
103
|
+
if ((sorted_array.size == 2) && (sorted_array[0] > sorted_array[1]))
|
104
|
+
return sorted_array.swap!(0, 1)
|
105
|
+
else
|
106
|
+
return sorted_array
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
middle = sorted_array.size / 2
|
111
|
+
array_1 = split_array(sorted_array[0...middle])
|
112
|
+
array_2 = split_array(sorted_array[middle...sorted_array.size])
|
113
|
+
|
114
|
+
return merge_arrays(array_1, array_2)
|
115
|
+
end
|
116
|
+
|
117
|
+
def merge_arrays(array_1, array_2)
|
118
|
+
sorted_array = Array.new()
|
119
|
+
|
120
|
+
while (array_1.any? && array_2.any?) # Iterador array_3
|
121
|
+
if (array_1[0] <= array_2[0])
|
122
|
+
sorted_array.push(array_1[0])
|
123
|
+
array_1.delete_at(0)
|
124
|
+
else
|
125
|
+
sorted_array.push(array_2[0])
|
126
|
+
array_2.delete_at(0)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
sorted_array.concat(array_1) if array_1.any?
|
131
|
+
sorted_array.concat(array_2) if array_2.any?
|
132
|
+
return sorted_array
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
data/lib/food/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,216 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: foodAX
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Angel Igareta
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: benchmark-ips
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: coveralls
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: terminal-table
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Practica dessarrollada dirigida a pruebas TDD.
|
140
|
+
email:
|
141
|
+
- alu0100967111@ull.edu.es
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".coveralls.yml"
|
147
|
+
- ".gitignore"
|
148
|
+
- ".travis.yml"
|
149
|
+
- Gemfile
|
150
|
+
- Guardfile
|
151
|
+
- LICENSE.txt
|
152
|
+
- README.md
|
153
|
+
- Rakefile
|
154
|
+
- bin/console
|
155
|
+
- bin/setup
|
156
|
+
- docs/DLLModule.html
|
157
|
+
- docs/DLLModule/DLL.html
|
158
|
+
- docs/DLLModule/Node.html
|
159
|
+
- docs/Food.html
|
160
|
+
- docs/FoodAbstract.html
|
161
|
+
- docs/FoodGem.html
|
162
|
+
- docs/_config.yml
|
163
|
+
- docs/_index.html
|
164
|
+
- docs/class_list.html
|
165
|
+
- docs/css/common.css
|
166
|
+
- docs/css/full_list.css
|
167
|
+
- docs/css/style.css
|
168
|
+
- docs/file.README.html
|
169
|
+
- docs/file_list.html
|
170
|
+
- docs/frames.html
|
171
|
+
- docs/index.html
|
172
|
+
- docs/input/dish_recipes.txt
|
173
|
+
- docs/input/food-data.txt
|
174
|
+
- docs/input/samples-data.txt
|
175
|
+
- docs/js/app.js
|
176
|
+
- docs/js/full_list.js
|
177
|
+
- docs/js/jquery.js
|
178
|
+
- docs/method_list.html
|
179
|
+
- docs/top-level-namespace.html
|
180
|
+
- food.gemspec
|
181
|
+
- input/dish_recipes.txt
|
182
|
+
- input/food-data.txt
|
183
|
+
- input/samples-data.txt
|
184
|
+
- lib/dsl/harvard_dish.rb
|
185
|
+
- lib/food.rb
|
186
|
+
- lib/food/dll.rb
|
187
|
+
- lib/food/food_class.rb
|
188
|
+
- lib/food/functions.rb
|
189
|
+
- lib/food/sort.rb
|
190
|
+
- lib/food/version.rb
|
191
|
+
homepage: https://github.com/ULL-ESIT-LPP-1718/tdd-alu0100967111
|
192
|
+
licenses:
|
193
|
+
- MIT
|
194
|
+
metadata:
|
195
|
+
allowed_push_host: https://rubygems.org
|
196
|
+
post_install_message:
|
197
|
+
rdoc_options: []
|
198
|
+
require_paths:
|
199
|
+
- lib
|
200
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: '0'
|
205
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
206
|
+
requirements:
|
207
|
+
- - ">="
|
208
|
+
- !ruby/object:Gem::Version
|
209
|
+
version: '0'
|
210
|
+
requirements: []
|
211
|
+
rubyforge_project:
|
212
|
+
rubygems_version: 2.5.1
|
213
|
+
signing_key:
|
214
|
+
specification_version: 4
|
215
|
+
summary: Practicas TDD.
|
216
|
+
test_files: []
|