watch_tower 0.0.1.beta5 → 0.0.1.beta6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -1
- data/Gemfile +1 -0
- data/README.md +70 -42
- data/lib/watch_tower/appscript.rb +2 -65
- data/lib/watch_tower/cli/install.rb +47 -20
- data/lib/watch_tower/editor/base_ps.rb +9 -1
- data/lib/watch_tower/editor/extensions/watchtower.vim +20 -0
- data/lib/watch_tower/editor/textmate.rb +8 -2
- data/lib/watch_tower/editor/vim.rb +113 -0
- data/lib/watch_tower/editor/xcode.rb +6 -1
- data/lib/watch_tower/editor.rb +2 -1
- data/lib/watch_tower/errors.rb +4 -1
- data/lib/watch_tower/eye.rb +4 -2
- data/lib/watch_tower/version.rb +1 -1
- data/lib/watch_tower.rb +24 -4
- data/spec/watch_tower/appscript_spec.rb +1 -25
- data/spec/watch_tower/editor/textmate_spec.rb +44 -34
- data/spec/watch_tower/editor/vim_spec.rb +162 -0
- data/spec/watch_tower/eye_spec.rb +7 -0
- data/watch_tower.gemspec +27 -10
- metadata +105 -70
data/lib/watch_tower.rb
CHANGED
@@ -22,6 +22,7 @@ TEMPLATE_PATH = File.join(LIB_PATH, 'templates')
|
|
22
22
|
USER_PATH = File.expand_path(File.join(ENV['HOME'], '.watch_tower'))
|
23
23
|
DATABASE_PATH = File.join(USER_PATH, 'databases')
|
24
24
|
LOG_PATH = File.join(USER_PATH, 'log')
|
25
|
+
EDITOR_EXTENSIONS_PATH = File.join(LIB_PATH, 'editor', 'extensions')
|
25
26
|
|
26
27
|
# Define the environment by default set to development
|
27
28
|
ENV['WATCH_TOWER_ENV'] ||= 'development'
|
@@ -33,6 +34,8 @@ FileUtils.mkdir_p LOG_PATH
|
|
33
34
|
|
34
35
|
# module WatchTower
|
35
36
|
module WatchTower
|
37
|
+
# Make sure all the methods are available as both Class and Instance methods.
|
38
|
+
extend self
|
36
39
|
|
37
40
|
# Create a logger
|
38
41
|
LOG = Logger.new(File.join(LOG_PATH, "#{ENV['WATCH_TOWER_ENV']}.log"))
|
@@ -44,23 +47,40 @@ module WatchTower
|
|
44
47
|
# Returh the threads
|
45
48
|
#
|
46
49
|
# @return [Hash] Threads
|
47
|
-
def
|
50
|
+
def threads
|
48
51
|
@@threads
|
49
52
|
end
|
50
53
|
|
51
54
|
# Get WatchTower's environment
|
52
55
|
#
|
53
56
|
# @return [String] The current environment
|
54
|
-
def
|
57
|
+
def env
|
55
58
|
ENV['WATCH_TOWER_ENV']
|
56
59
|
end
|
57
60
|
|
58
61
|
# Set WatchTower's environment
|
59
62
|
#
|
60
63
|
# @param [String] The environment
|
61
|
-
def
|
64
|
+
def env=(environment)
|
62
65
|
ENV['WATCH_TOWER_ENV'] = environment
|
63
66
|
end
|
67
|
+
|
68
|
+
# Cross-platform way of finding an executable in the $PATH.
|
69
|
+
#
|
70
|
+
# Taken from hub
|
71
|
+
# https://github.com/defunkt/hub/blob/master/lib/hub/context.rb#L186
|
72
|
+
#
|
73
|
+
# which('ruby') #=> /usr/bin/ruby
|
74
|
+
def which(cmd)
|
75
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
76
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
77
|
+
exts.each { |ext|
|
78
|
+
exe = "#{path}/#{cmd}#{ext}"
|
79
|
+
return exe if File.executable? exe
|
80
|
+
}
|
81
|
+
end
|
82
|
+
return nil
|
83
|
+
end
|
64
84
|
end
|
65
85
|
|
66
86
|
# Make sure we are running UTF-8
|
@@ -76,4 +96,4 @@ require "watch_tower/editor"
|
|
76
96
|
require "watch_tower/project"
|
77
97
|
require "watch_tower/eye"
|
78
98
|
require "watch_tower/file_tree"
|
79
|
-
require "watch_tower/server"
|
99
|
+
require "watch_tower/server"
|
@@ -8,33 +8,9 @@ module ::Appscript
|
|
8
8
|
extend ::Appscript
|
9
9
|
end
|
10
10
|
end
|
11
|
-
describe "#app" do
|
12
11
|
|
12
|
+
describe "#app" do
|
13
13
|
it { should respond_to :app }
|
14
|
-
|
15
|
-
it "should return an instance of Application" do
|
16
|
-
subject.app.should be_instance_of ::Appscript::Application
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "#its" do
|
21
|
-
it { should respond_to :its }
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "#name" do
|
25
|
-
it { should respond_to :name }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
describe "Application" do
|
30
|
-
subject { ::Appscript.app('TextMate') }
|
31
|
-
|
32
|
-
[:name, :version, :processes, :unix_id, :by_pid, :is_running?].each do |method|
|
33
|
-
it "should respond to #{method}" do
|
34
|
-
-> {
|
35
|
-
subject.send(method)
|
36
|
-
}.should_not raise_error NoMethodError
|
37
|
-
end
|
38
14
|
end
|
39
15
|
end
|
40
16
|
end
|
@@ -2,21 +2,41 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Editor
|
4
4
|
describe Textmate do
|
5
|
+
before(:each) do
|
6
|
+
@file_path = '/path/to/file.rb'
|
7
|
+
@app = mock()
|
8
|
+
@app.stubs(:is_running?).returns(true)
|
9
|
+
@documents = mock
|
10
|
+
@document = mock
|
11
|
+
@path = mock
|
12
|
+
@path.stubs(:get).returns(@file_path)
|
13
|
+
@document.stubs(:path).returns(@path)
|
14
|
+
@documents.stubs(:get).returns([@document])
|
15
|
+
@app.stubs(:document).returns(@documents)
|
16
|
+
@name = mock
|
17
|
+
@name.stubs(:get).returns("TextMate")
|
18
|
+
@app.stubs(:name).returns(@name)
|
19
|
+
@version = mock
|
20
|
+
@version.stubs(:get).returns("1.5.10")
|
21
|
+
@app.stubs(:version).returns(@version)
|
22
|
+
Textmate.any_instance.stubs(:editor).returns(@app)
|
23
|
+
end
|
24
|
+
|
5
25
|
it { should respond_to :current_path }
|
6
26
|
|
7
27
|
it { should respond_to :name }
|
8
28
|
its(:name) { should_not raise_error NotImplementedError }
|
29
|
+
its(:name) { should_not be_empty }
|
9
30
|
|
10
31
|
it { should respond_to :version }
|
11
32
|
its(:version) { should_not raise_error NotImplementedError }
|
33
|
+
its(:version) { should_not be_empty }
|
12
34
|
|
13
35
|
describe "#is_running?" do
|
14
36
|
it { should respond_to :is_running? }
|
15
37
|
|
16
38
|
it "should return wether Textmate is running or not" do
|
17
|
-
app
|
18
|
-
app.expects(:is_running?).returns(true).once
|
19
|
-
Textmate.any_instance.stubs(:editor).returns(app)
|
39
|
+
@app.expects(:is_running?).returns(true).once
|
20
40
|
|
21
41
|
subject.is_running?.should be_true
|
22
42
|
end
|
@@ -26,24 +46,19 @@ module Editor
|
|
26
46
|
it { should respond_to :current_path }
|
27
47
|
|
28
48
|
it "should return the current_path if textmate running" do
|
29
|
-
app
|
30
|
-
|
31
|
-
|
32
|
-
document
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
app.expects(:document).returns(documents).once
|
38
|
-
Textmate.any_instance.stubs(:editor).returns(app)
|
39
|
-
|
40
|
-
subject.current_path.should == '/path/to/file.rb'
|
49
|
+
@app.expects(:is_running?).returns(true).once
|
50
|
+
@path.expects(:get).returns(@file_path).once
|
51
|
+
@document.expects(:path).returns(@path).once
|
52
|
+
@documents.expects(:get).returns([@document]).once
|
53
|
+
@app.expects(:document).returns(@documents).once
|
54
|
+
Textmate.any_instance.stubs(:editor).returns(@app)
|
55
|
+
|
56
|
+
subject.current_path.should == @file_path
|
41
57
|
end
|
42
58
|
|
43
59
|
it "should return nil if textmate ain't running" do
|
44
|
-
app
|
45
|
-
|
46
|
-
Textmate.any_instance.stubs(:editor).returns(app)
|
60
|
+
@app.expects(:is_running?).returns(false).once
|
61
|
+
Textmate.any_instance.stubs(:editor).returns(@app)
|
47
62
|
|
48
63
|
subject.current_path.should be_nil
|
49
64
|
end
|
@@ -53,28 +68,23 @@ module Editor
|
|
53
68
|
it { should respond_to :current_paths }
|
54
69
|
|
55
70
|
it "should return the current_paths if textmate running" do
|
56
|
-
app
|
57
|
-
|
58
|
-
|
59
|
-
document
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
app.expects(:document).returns(documents).once
|
65
|
-
Textmate.any_instance.stubs(:editor).returns(app)
|
66
|
-
|
67
|
-
subject.current_paths.should == ['/path/to/file.rb']
|
71
|
+
@app.expects(:is_running?).returns(true).once
|
72
|
+
@path.expects(:get).returns(@file_path).once
|
73
|
+
@document.expects(:path).returns(@path).once
|
74
|
+
@documents.expects(:get).returns([@document]).once
|
75
|
+
@app.expects(:document).returns(@documents).once
|
76
|
+
Textmate.any_instance.stubs(:editor).returns(@app)
|
77
|
+
|
78
|
+
subject.current_paths.should == [@file_path]
|
68
79
|
end
|
69
80
|
|
70
81
|
it "should return nil if textmate ain't running" do
|
71
|
-
app
|
72
|
-
|
73
|
-
Textmate.any_instance.stubs(:editor).returns(app)
|
82
|
+
@app.expects(:is_running?).returns(false).once
|
83
|
+
Textmate.any_instance.stubs(:editor).returns(@app)
|
74
84
|
|
75
85
|
subject.current_paths.should be_nil
|
76
86
|
end
|
77
87
|
end
|
78
88
|
|
79
89
|
end
|
80
|
-
end
|
90
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Editor
|
4
|
+
describe Vim do
|
5
|
+
before(:each) do
|
6
|
+
# Stubs which
|
7
|
+
WatchTower.stubs(:which).with('vim').returns('/usr/bin/vim')
|
8
|
+
WatchTower.stubs(:which).with('gvim').returns('/usr/bin/gvim')
|
9
|
+
WatchTower.stubs(:which).with('mvim').returns(nil)
|
10
|
+
|
11
|
+
# Stub systemu
|
12
|
+
Vim.any_instance.stubs(:systemu).with("/usr/bin/vim --help").returns([0, "", ""])
|
13
|
+
Vim.any_instance.stubs(:systemu).with("/usr/bin/gvim --help").returns([0, "--remote server", ""])
|
14
|
+
Vim.any_instance.stubs(:systemu).with("/usr/bin/gvim --servername VIM --remote-send ':source #{Vim::VIM_EXTENSION_PATH}<CR>'")
|
15
|
+
Vim.any_instance.stubs(:systemu).with("/usr/bin/gvim --servername VIM --remote-expr 'watchtower#ls()'").returns([0, <<-EOS, ''])
|
16
|
+
/path/to/file.rb
|
17
|
+
EOS
|
18
|
+
Vim.any_instance.stubs(:systemu).with('/usr/bin/gvim --serverlist').returns([0, <<-EOC, ''])
|
19
|
+
VIM
|
20
|
+
EOC
|
21
|
+
Vim.any_instance.stubs(:systemu).with("/usr/bin/gvim --version").
|
22
|
+
returns [0, <<-EOV, '']
|
23
|
+
VIM - Vi IMproved 7.3 (2010 Aug 15)
|
24
|
+
Included patches: 1-202, 204-222, 224-322
|
25
|
+
Compiled by 'http://www.opensuse.org/'
|
26
|
+
Huge version without GUI. Features included (+) or not (-):
|
27
|
+
+arabic +autocmd -balloon_eval -browse ++builtin_terms +byte_offset +cindent
|
28
|
+
-clientserver -clipboard +cmdline_compl +cmdline_hist +cmdline_info +comments
|
29
|
+
+conceal +cryptv +cscope +cursorbind +cursorshape +dialog_con +diff +digraphs
|
30
|
+
-dnd -ebcdic +emacs_tags +eval +ex_extra +extra_search +farsi +file_in_path
|
31
|
+
+find_in_path +float +folding -footer +fork() +gettext -hangul_input +iconv
|
32
|
+
+insert_expand +jumplist +keymap +langmap +libcall +linebreak +lispindent
|
33
|
+
+listcmds +localmap -lua +menu +mksession +modify_fname +mouse -mouseshape
|
34
|
+
+mouse_dec -mouse_gpm -mouse_jsbterm +mouse_netterm -mouse_sysmouse
|
35
|
+
+mouse_xterm +multi_byte +multi_lang -mzscheme +netbeans_intg +path_extra -perl
|
36
|
+
+persistent_undo +postscript +printer +profile -python -python3 +quickfix
|
37
|
+
+reltime +rightleft -ruby +scrollbind +signs +smartindent +sniff +startuptime
|
38
|
+
+statusline -sun_workshop +syntax +tag_binary +tag_old_static -tag_any_white
|
39
|
+
-tcl +terminfo +termresponse +textobjects +title -toolbar +user_commands
|
40
|
+
+vertsplit +virtualedit +visual +visualextra +viminfo +vreplace +wildignore
|
41
|
+
+wildmenu +windows +writebackup -X11 -xfontset -xim -xsmp -xterm_clipboard
|
42
|
+
-xterm_save
|
43
|
+
system vimrc file: "/etc/vimrc"
|
44
|
+
user vimrc file: "$HOME/.vimrc"
|
45
|
+
user exrc file: "$HOME/.exrc"
|
46
|
+
fall-back for $VIM: "/etc"
|
47
|
+
f-b for $VIMRUNTIME: "/usr/share/vim/current"
|
48
|
+
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -I/usr/local/include -fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe -fno-strict-aliasing -fstack-protector-all
|
49
|
+
Linking: gcc -L/usr/local/lib -Wl,--as-needed -o vim -lm -lnsl -lncurses -lacl -lattr -ldl
|
50
|
+
EOV
|
51
|
+
end
|
52
|
+
|
53
|
+
it { should respond_to :name }
|
54
|
+
its(:name) { should_not raise_error NotImplementedError }
|
55
|
+
its(:name) { should_not be_empty }
|
56
|
+
|
57
|
+
it { should respond_to :version }
|
58
|
+
its(:version) { should_not raise_error NotImplementedError }
|
59
|
+
its(:version) { should_not be_empty }
|
60
|
+
its(:version) { should == '7.3' }
|
61
|
+
|
62
|
+
describe "#supported_vims" do
|
63
|
+
it { should respond_to :supported_vims }
|
64
|
+
|
65
|
+
it "should return gvim" do
|
66
|
+
Vim.any_instance.expects(:systemu).with("/usr/bin/vim --help").returns([0, "", ""]).once
|
67
|
+
Vim.any_instance.expects(:systemu).with("/usr/bin/gvim --help").returns([0, "--remote server", ""]).once
|
68
|
+
WatchTower.expects(:which).with('vim').returns('/usr/bin/vim').once
|
69
|
+
WatchTower.expects(:which).with('gvim').returns('/usr/bin/gvim').once
|
70
|
+
WatchTower.expects(:which).with('mvim').returns(nil).once
|
71
|
+
|
72
|
+
subject.send :supported_vims
|
73
|
+
subject.instance_variable_get('@vims').should == ['/usr/bin/gvim']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#editor" do
|
78
|
+
it { should respond_to :editor }
|
79
|
+
|
80
|
+
it "should return /usr/bin/gvim" do
|
81
|
+
subject.send(:editor).should == '/usr/bin/gvim'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#servers" do
|
86
|
+
it { should respond_to :servers }
|
87
|
+
|
88
|
+
it "should return VIM" do
|
89
|
+
Vim.any_instance.expects(:systemu).with('/usr/bin/gvim --serverlist').returns([0, <<-EOC, '']).once
|
90
|
+
VIM
|
91
|
+
EOC
|
92
|
+
subject.send(:servers).should == ['VIM']
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "#send_extensions_to_editor" do
|
97
|
+
it { should respond_to :send_extensions_to_editor }
|
98
|
+
|
99
|
+
it "should send the extensions to vim" do
|
100
|
+
Vim.any_instance.expects(:systemu).with("/usr/bin/gvim --servername VIM --remote-send ':source #{Vim::VIM_EXTENSION_PATH}<CR>'").once
|
101
|
+
|
102
|
+
subject.send :send_extensions_to_editor
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "#is_running?" do
|
107
|
+
it { should respond_to :is_running? }
|
108
|
+
|
109
|
+
it "should return true if ViM is running" do
|
110
|
+
subject.is_running?.should be_true
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#current_paths" do
|
115
|
+
it { should respond_to :current_paths }
|
116
|
+
|
117
|
+
it "should call is_running?" do
|
118
|
+
Vim.any_instance.expects(:is_running?).returns(false).once
|
119
|
+
|
120
|
+
subject.current_paths
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should call send_extensions_to_editor" do
|
124
|
+
Vim.any_instance.expects(:send_extensions_to_editor).once
|
125
|
+
|
126
|
+
subject.current_paths
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should be nil if is_running? is false" do
|
130
|
+
Vim.any_instance.stubs(:is_running?).returns(false)
|
131
|
+
|
132
|
+
subject.current_paths.should be_nil
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should be able to parse ls output" do
|
136
|
+
Vim.any_instance.expects(:systemu).with("/usr/bin/gvim --servername VIM --remote-expr 'watchtower#ls()'").returns([0, <<-EOS, '']).once
|
137
|
+
/path/to/file.rb
|
138
|
+
/path/to/file2.rb
|
139
|
+
EOS
|
140
|
+
|
141
|
+
documents = subject.current_paths
|
142
|
+
documents.should include("/path/to/file.rb")
|
143
|
+
documents.should include("/path/to/file2.rb")
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should not return duplicate documents" do
|
147
|
+
Vim.any_instance.expects(:systemu).with("/usr/bin/gvim --servername VIM --remote-expr 'watchtower#ls()'").returns([0, <<-EOS, '']).once
|
148
|
+
/path/to/file.rb
|
149
|
+
/path/to/file.rb
|
150
|
+
/path/to/file.rb
|
151
|
+
/path/to/file.rb
|
152
|
+
/path/to/file.rb
|
153
|
+
EOS
|
154
|
+
|
155
|
+
documents = subject.current_paths
|
156
|
+
documents.should include("/path/to/file.rb")
|
157
|
+
documents.size.should == 1
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
@@ -10,6 +10,7 @@ describe Eye do
|
|
10
10
|
@project_path = '/home/user/Code/OpenSource/watch_tower'
|
11
11
|
@project_name = 'watch_tower'
|
12
12
|
::File.stubs(:exists?).with(@file_path).returns(true)
|
13
|
+
::File.stubs(:file?).with(@file_path).returns(true)
|
13
14
|
|
14
15
|
# Mock the editor
|
15
16
|
@editor = mock
|
@@ -74,6 +75,12 @@ describe Eye do
|
|
74
75
|
subject.start
|
75
76
|
end
|
76
77
|
|
78
|
+
it "should call File.file?" do
|
79
|
+
::File.expects(:file?).with(@file_path).returns(true).once
|
80
|
+
|
81
|
+
subject.start
|
82
|
+
end
|
83
|
+
|
77
84
|
it "shouldn't add the file if it matches the ignore list" do
|
78
85
|
ignored_path = '/path/to/project/.git/COMMIT_MESSAGE'
|
79
86
|
::File.stubs(:exists?).with(ignored_path).returns(true)
|
data/watch_tower.gemspec
CHANGED
@@ -10,17 +10,28 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.email = ["wael.nasreddine@gmail.com"]
|
11
11
|
s.homepage = "https://github.com/TechnoGate/watch_tower"
|
12
12
|
s.summary = <<-MSG
|
13
|
-
WatchTower helps you track
|
14
|
-
|
13
|
+
WatchTower helps you track how much time you spend on all of your projects, at
|
14
|
+
the project, directory, and file level.
|
15
15
|
MSG
|
16
16
|
s.description = <<-MSG
|
17
|
-
Did you ever
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
Did you ever want to keep track of how much time you _really_ spend on all of
|
18
|
+
your projects? Sure, you can try to remember to keep running estimates of your
|
19
|
+
time in the hope that you can aggregate those estimates later into some
|
20
|
+
meaningful data. But sometimes you forget, or an error creeps into your
|
21
|
+
estimate. And those errors add up. Quickly.
|
22
|
+
|
23
|
+
You can try some tracking software that depends on you to start and stop
|
24
|
+
timers. But what happens if you forget to start or stop one of those timers?
|
25
|
+
|
26
|
+
What you need is a passive system that will take care of all of this for you,
|
27
|
+
so you can focus on the actual work, which is where WatchTower comes into
|
28
|
+
play.
|
29
|
+
|
30
|
+
WatchTower runs in the background and keeps track of the time spent editing
|
31
|
+
each file with one of the supported editors (listed below). Since WatchTower
|
32
|
+
keeps track of the time spent on each file, and it knows which project each
|
33
|
+
file belongs to, you can view details and statistics on each project, right
|
34
|
+
down to the file level.
|
24
35
|
MSG
|
25
36
|
|
26
37
|
s.files = `git ls-files`.split("\n")
|
@@ -58,6 +69,12 @@ MSG
|
|
58
69
|
s.add_dependency 'sass', '~>3.1.10'
|
59
70
|
s.add_dependency 'sprockets', '~>2.0.2'
|
60
71
|
|
72
|
+
# System commands
|
73
|
+
s.add_dependency 'systemu', '~>2.4.0'
|
74
|
+
|
75
|
+
# Crontab editor
|
76
|
+
s.add_dependency 'cronedit', '~>0.3.0' if RbConfig::CONFIG['target_os'] =~ /linux/i
|
77
|
+
|
61
78
|
####
|
62
79
|
# Development dependencies
|
63
80
|
####
|
@@ -94,4 +111,4 @@ MSG
|
|
94
111
|
# Debugging
|
95
112
|
####
|
96
113
|
s.add_development_dependency 'pry', '~>0.9.6.2'
|
97
|
-
end
|
114
|
+
end
|