syc-task 0.0.7 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +159 -15
- data/bin/console_timer +75 -0
- data/bin/syctask +246 -68
- data/lib/syctask.rb +4 -1
- data/lib/syctask/environment.rb +427 -2
- data/lib/syctask/schedule.rb +84 -21
- data/lib/syctask/settings.rb +43 -0
- data/lib/syctask/statistics.rb +196 -0
- data/lib/syctask/task.rb +58 -2
- data/lib/syctask/task_planner.rb +94 -13
- data/lib/syctask/task_scheduler.rb +5 -1
- data/lib/syctask/task_service.rb +55 -15
- data/lib/syctask/task_tracker.rb +27 -17
- data/lib/syctask/times.rb +29 -0
- data/lib/syctask/version.rb +1 -1
- data/lib/syctime/time_util.rb +46 -7
- data/lib/sycutil/console_timer.rb +75 -0
- metadata +215 -136
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'schedule.rb'
|
2
|
+
require_relative 'environment.rb'
|
2
3
|
|
3
4
|
module Syctask
|
4
5
|
|
@@ -37,7 +38,7 @@ module Syctask
|
|
37
38
|
ASSIGNMENT_PATTERN = /([a-zA-Z]):(\d+(?:,\d+|\d+;)*)/
|
38
39
|
|
39
40
|
# Working directory
|
40
|
-
WORK_DIR = File.expand_path("~/.tasks")
|
41
|
+
WORK_DIR = Syctask::SYC_DIR #File.expand_path("~/.tasks")
|
41
42
|
|
42
43
|
# Creates a new TaskScheduler.
|
43
44
|
def initialize
|
@@ -54,6 +55,7 @@ module Syctask
|
|
54
55
|
unless sequential?(@work_time)
|
55
56
|
raise Exception, "Begin time has to be before end time"
|
56
57
|
end
|
58
|
+
Syctask::log_work_time("work", @work_time)
|
57
59
|
end
|
58
60
|
|
59
61
|
# Set the busy times. Raises an exception if one begin time is after start
|
@@ -66,12 +68,14 @@ module Syctask
|
|
66
68
|
raise Exception, "Begin time has to be before end time"
|
67
69
|
end
|
68
70
|
end
|
71
|
+
Syctask::log_meetings("meeting", @busy_time, @meetings)
|
69
72
|
end
|
70
73
|
|
71
74
|
# Sets the titles of the meetings (busy times)
|
72
75
|
# Invokation: set_meeting_titles("title1,title2,title3")
|
73
76
|
def set_meeting_titles(titles)
|
74
77
|
@meetings = titles.split(",") if titles
|
78
|
+
Syctask::log_meetings("meeting", @busy_time, @meetings)
|
75
79
|
end
|
76
80
|
|
77
81
|
# Sets the tasks for scheduling
|
data/lib/syctask/task_service.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
+
require 'csv'
|
1
2
|
require 'yaml'
|
3
|
+
require_relative 'environment.rb'
|
2
4
|
|
3
5
|
# Syctask provides functions for managing tasks in a task list
|
4
6
|
module Syctask
|
@@ -8,7 +10,7 @@ module Syctask
|
|
8
10
|
class TaskService
|
9
11
|
# Default directory where the tasks are saved to if no directory is
|
10
12
|
# specified
|
11
|
-
DEFAULT_DIR = File.expand_path("~/.tasks")
|
13
|
+
DEFAULT_DIR = Syctask::WORK_DIR #File.expand_path("~/.tasks")
|
12
14
|
|
13
15
|
# Creates a new task in the specified directory, with the specified options
|
14
16
|
# and the specified title. If the directory doesn't exist it is created.
|
@@ -22,15 +24,18 @@ module Syctask
|
|
22
24
|
# * tags - can be used to searching tasks that belong to a certain category
|
23
25
|
def create(dir, options, title)
|
24
26
|
create_dir(dir)
|
25
|
-
task = Task.new(options, title,
|
27
|
+
task = Task.new(options, title, next_id(dir))
|
26
28
|
save(dir, task)
|
29
|
+
Syctask::log_task("create", task)
|
27
30
|
task.id
|
28
31
|
end
|
29
32
|
|
30
33
|
# Reads the task with given ID id located in given directory dir. If task
|
31
34
|
# does not exist nil is returned otherwise the task is returned
|
32
35
|
def read(dir, id)
|
33
|
-
task =
|
36
|
+
task = read_by_id(id)
|
37
|
+
return task unless task.nil?
|
38
|
+
#task = nil
|
34
39
|
Dir.glob("#{dir}/*.task").each do |file|
|
35
40
|
task = YAML.load_file(file) if File.file? file
|
36
41
|
if not task.nil? and task.class == Syctask::Task and task.id == id.to_i
|
@@ -40,6 +45,16 @@ module Syctask
|
|
40
45
|
nil
|
41
46
|
end
|
42
47
|
|
48
|
+
# Reads the task identified by ID. If no task with ID is found nil is
|
49
|
+
# returned otherwise the task
|
50
|
+
def read_by_id(id)
|
51
|
+
return nil unless File.exists? Syctask::IDS
|
52
|
+
ids = File.read(Syctask::IDS)
|
53
|
+
entry = ids.scan(/(^#{id}),(.*\n)/)[0]
|
54
|
+
return YAML.load_file(entry[1].chomp) if entry
|
55
|
+
return nil
|
56
|
+
end
|
57
|
+
|
43
58
|
# Finds all tasks that match the given filter. The filter can be provided
|
44
59
|
# for :id, :title, :description, :follow_up, :due, :tags and :prio.
|
45
60
|
# id can be eather a selection of IDs ID1,ID2,ID3 or a comparison <|=|>ID.
|
@@ -52,7 +67,7 @@ module Syctask
|
|
52
67
|
# open tasks
|
53
68
|
def find(dir, filter={}, all=true)
|
54
69
|
tasks = []
|
55
|
-
Dir.glob("#{dir}
|
70
|
+
Dir.glob("#{dir}/*.task").sort.each do |file|
|
56
71
|
begin
|
57
72
|
File.file?(file) ? task = YAML.load_file(file) : next
|
58
73
|
rescue Exception => e
|
@@ -78,12 +93,16 @@ module Syctask
|
|
78
93
|
# new value. If note and tags are provided these are added to the existing
|
79
94
|
# values.
|
80
95
|
def update(dir, id, options)
|
81
|
-
|
82
|
-
task
|
96
|
+
task = read_by_id(id)
|
97
|
+
unless task
|
98
|
+
task_file = Dir.glob("#{dir}/#{id}.task")[0]
|
99
|
+
task = YAML.load_file(task_file) if task_file
|
100
|
+
end
|
83
101
|
updated = false
|
84
102
|
if task
|
85
103
|
task.update(options)
|
86
|
-
save(dir, task)
|
104
|
+
save(task.dir, task)
|
105
|
+
Syctask::log_task("update", task)
|
87
106
|
updated = true
|
88
107
|
end
|
89
108
|
updated
|
@@ -94,7 +113,7 @@ module Syctask
|
|
94
113
|
# returned
|
95
114
|
def delete(dir, filter)
|
96
115
|
deleted = 0
|
97
|
-
Dir.glob("#{dir}
|
116
|
+
Dir.glob("#{dir}/*.task").each do |file|
|
98
117
|
begin
|
99
118
|
File.file?(file) ? task = YAML.load_file(file) : next
|
100
119
|
rescue Exception => e
|
@@ -103,6 +122,9 @@ module Syctask
|
|
103
122
|
next unless not task.nil? and task.class == Syctask::Task
|
104
123
|
if task.matches?(filter)
|
105
124
|
deleted += File.delete(file)
|
125
|
+
ids = File.read(Syctask::IDS)
|
126
|
+
File.write(Syctask::IDS, ids.gsub("#{task.id},#{file}",""))
|
127
|
+
Syctask::log_task("delete", task)
|
106
128
|
end
|
107
129
|
end
|
108
130
|
deleted
|
@@ -112,7 +134,11 @@ module Syctask
|
|
112
134
|
# ~/.tasks will be set.
|
113
135
|
def save(dir, task)
|
114
136
|
task.dir = dir.nil? ? DEFAULT_DIR : File.expand_path(dir)
|
115
|
-
|
137
|
+
task_file = "#{task.dir}/#{task.id}.task"
|
138
|
+
unless File.exists? task_file
|
139
|
+
File.open(Syctask::IDS, 'a') {|f| f.puts "#{task.id},#{task_file}"}
|
140
|
+
end
|
141
|
+
File.open(task_file, 'w') {|f| YAML.dump(task, f)}
|
116
142
|
end
|
117
143
|
|
118
144
|
private
|
@@ -122,18 +148,32 @@ module Syctask
|
|
122
148
|
FileUtils.mkdir_p dir unless File.exists? dir
|
123
149
|
end
|
124
150
|
|
125
|
-
#
|
126
|
-
# The task's file name is in the form ID.task.
|
127
|
-
# the biggest number and adds one to
|
128
|
-
|
129
|
-
|
151
|
+
# Checks for the next possible task's ID based on the tasks available in
|
152
|
+
# the task directory. The task's file name is in the form ID.task.
|
153
|
+
# local_ID seeks for the biggest number and adds one to determine the
|
154
|
+
# next valid task ID.
|
155
|
+
def local_id(dir)
|
156
|
+
tasks = Dir.glob("#{dir}/*.task")
|
130
157
|
ids = []
|
131
158
|
tasks.each do |task|
|
132
159
|
id = File.basename(task).scan(/^\d+(?=\.task)/)[0]
|
133
160
|
ids << id.to_i if id
|
134
161
|
end
|
135
162
|
ids.empty? ? 1 : ids.sort[ids.size-1] + 1
|
136
|
-
|
163
|
+
end
|
164
|
+
|
165
|
+
# Retrieves a new unique ID for a task. If next id is less than the next
|
166
|
+
# ID in the directory a warning is printed and the higher ID is taken as
|
167
|
+
# the next ID.
|
168
|
+
def next_id(dir)
|
169
|
+
local = local_id(dir)
|
170
|
+
id = File.readlines(Syctask::ID)[0] if File.exists? Syctask::ID
|
171
|
+
id = id ? id.to_i + 1 : 1
|
172
|
+
STDERR.puts "Warning: global id < local id" if id < local
|
173
|
+
id = [id, local].max
|
174
|
+
File.open(Syctask::ID, 'w') {|f| f.puts id}
|
175
|
+
id
|
176
|
+
end
|
137
177
|
|
138
178
|
end
|
139
179
|
end
|
data/lib/syctask/task_tracker.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'fileutils'
|
1
3
|
require_relative 'environment.rb'
|
2
4
|
require_relative 'task_service.rb'
|
5
|
+
#require_relative '../sycutil/console_timer.rb'
|
3
6
|
|
4
7
|
module Syctask
|
5
8
|
|
@@ -14,9 +17,9 @@ module Syctask
|
|
14
17
|
class TaskTracker
|
15
18
|
|
16
19
|
# File name of the file where the tracked files are saved to
|
17
|
-
TRACKED_TASKS_FILE = Syctask::WORK_DIR + '/' + 'tracked_tasks'
|
20
|
+
TRACKED_TASKS_FILE = Syctask::TRACKED_TASK #Syctask::WORK_DIR + '/' + 'tracked_tasks'
|
18
21
|
# File name of the task log file
|
19
|
-
TASK_LOG_FILE = Syctask::WORK_DIR + '/' + 'tasks.log'
|
22
|
+
TASK_LOG_FILE = Syctask::TASKS_LOG #Syctask::WORK_DIR + '/' + 'tasks.log'
|
20
23
|
|
21
24
|
# Creates a new TaskTracker
|
22
25
|
def initialize
|
@@ -26,19 +29,22 @@ module Syctask
|
|
26
29
|
|
27
30
|
# When a task is started it is saved with the start time. If a task is
|
28
31
|
# already tracked it is stopped (see #stop). A started task will print
|
29
|
-
# every
|
32
|
+
# every second a message to the console if the show parameter is true.
|
30
33
|
# start returns
|
31
34
|
# * [false, nil ] if the task is already tracked
|
32
35
|
# * [true, nil ] if the task is started and no task was running.
|
33
36
|
# * [true, task] if task is started and the previously running task stopped
|
34
|
-
def start(task)
|
37
|
+
def start(task, show=true)
|
38
|
+
raise ArgumentError, "Error: Task without directory.\n"+
|
39
|
+
"--> Update task with syctask -t <dir> update "+
|
40
|
+
"#{task.id}" unless task.dir
|
35
41
|
index = @tasks.find_index(task)
|
36
42
|
return [false, nil] if not index.nil? and index == 0
|
37
43
|
|
38
44
|
stopped_task = stop
|
39
45
|
track = Track.new(task)
|
40
46
|
|
41
|
-
track.start
|
47
|
+
track.start(show)
|
42
48
|
log_task(:start, track)
|
43
49
|
|
44
50
|
@tracks.insert(0,track)
|
@@ -59,18 +65,15 @@ module Syctask
|
|
59
65
|
return nil unless @tasks[0]
|
60
66
|
|
61
67
|
task = @tasks[0]
|
62
|
-
|
63
|
-
task.lead_time += @tracks[0].stop
|
64
|
-
else
|
65
|
-
task.lead_time = @tracks[0].stop
|
66
|
-
end
|
67
|
-
|
68
|
+
task.update_lead_time(@tracks[0].stop)
|
68
69
|
@service.save(task.dir, task)
|
70
|
+
|
69
71
|
log_task(:stop, @tracks[0])
|
70
72
|
|
71
73
|
@tracks.delete_at(0)
|
72
74
|
@tasks.delete_at(0)
|
73
75
|
save_tracks
|
76
|
+
|
74
77
|
task
|
75
78
|
end
|
76
79
|
|
@@ -99,7 +102,9 @@ module Syctask
|
|
99
102
|
else
|
100
103
|
@tracks ||= YAML.load_file(TRACKED_TASKS_FILE)
|
101
104
|
@tasks = []
|
102
|
-
@tracks
|
105
|
+
if @tracks
|
106
|
+
@tracks.each { |track| @tasks << @service.read(track.dir, track.id) }
|
107
|
+
end
|
103
108
|
end
|
104
109
|
end
|
105
110
|
|
@@ -108,7 +113,7 @@ module Syctask
|
|
108
113
|
FileUtils.mkdir_r Syctask::WORK_DIR unless File.exists? Syctask::WORK_DIR
|
109
114
|
File.open(TASK_LOG_FILE, 'a') do |file|
|
110
115
|
log_entry = "#{type.to_s};"
|
111
|
-
log_entry += "#{track.id}
|
116
|
+
log_entry += "#{track.id};#{track.dir};"
|
112
117
|
log_entry += "#{track.title};"
|
113
118
|
log_entry += "#{track.started};"
|
114
119
|
log_entry += "#{track.stopped}"
|
@@ -119,7 +124,7 @@ module Syctask
|
|
119
124
|
end
|
120
125
|
|
121
126
|
# A Track holds a task and stops the time the task is processed. The Track
|
122
|
-
# will print every
|
127
|
+
# will print every second the elapsed time and the time left to the
|
123
128
|
# specified Task#duration.
|
124
129
|
class Track
|
125
130
|
|
@@ -139,17 +144,22 @@ module Syctask
|
|
139
144
|
@dir = task.dir
|
140
145
|
@id = task.id
|
141
146
|
@title = task.title
|
147
|
+
@duration = task.remaining.to_i
|
148
|
+
@semaphore = "#{Syctask::SYC_DIR}/#{@id}.track"
|
142
149
|
end
|
143
150
|
|
144
|
-
# Starts the tracking and a timer that will print to STDOUT every
|
151
|
+
# Starts the tracking and a timer that will print to STDOUT every second
|
145
152
|
# the elapsed time and the time left until Task#duration
|
146
|
-
def start
|
153
|
+
def start(show)
|
147
154
|
@started ||= Time.now
|
148
|
-
# start a timer that prints
|
155
|
+
# start a timer that prints id and elapsed time
|
156
|
+
FileUtils.touch @semaphore
|
157
|
+
system "console_timer #{@duration} #{@id} #{@semaphore} &" if show
|
149
158
|
end
|
150
159
|
|
151
160
|
# Stops the task tracking and returns the lead time of the task
|
152
161
|
def stop
|
162
|
+
FileUtils.rm @semaphore if @semaphore and File.exists? @semaphore
|
153
163
|
@stopped ||= Time.now
|
154
164
|
@stopped - @started
|
155
165
|
end
|
data/lib/syctask/times.rb
CHANGED
@@ -20,6 +20,35 @@ module Syctask
|
|
20
20
|
@m > 0 ? @h+1 : @h
|
21
21
|
end
|
22
22
|
|
23
|
+
# Returns a Time object with the current date and the hour and minute of
|
24
|
+
# this Times object
|
25
|
+
def time
|
26
|
+
now = Time.now
|
27
|
+
Time.local(now.year,now.mon,now.day,@h,@m,0)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Calculates the difference between this time and the provided time. If no
|
31
|
+
# time is given the current time is used.
|
32
|
+
# Example:
|
33
|
+
# This time = 9:35
|
34
|
+
# New time = 10:20
|
35
|
+
# diff(time) = 0:45
|
36
|
+
# Will return [hour,min] in the example [0,45]
|
37
|
+
def diff(time = Time.now)
|
38
|
+
diff_minutes = (time.hour - @h) * 60 + (time.min - @m)
|
39
|
+
signum = diff_minutes == 0 ? 0 : diff_minutes / diff_minutes.abs
|
40
|
+
diff_h = diff_minutes.abs / 60
|
41
|
+
diff_m = diff_minutes.abs % 60
|
42
|
+
if signum < 0
|
43
|
+
if diff_h > 0
|
44
|
+
[signum * diff_h, diff_m]
|
45
|
+
else
|
46
|
+
[diff_h, signum * diff_m]
|
47
|
+
end
|
48
|
+
else
|
49
|
+
[diff_h, diff_m]
|
50
|
+
end
|
51
|
+
end
|
23
52
|
end
|
24
53
|
|
25
54
|
end
|
data/lib/syctask/version.rb
CHANGED
data/lib/syctime/time_util.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
1
3
|
# Functions for time operations
|
2
4
|
module Syctime
|
3
5
|
|
@@ -6,13 +8,13 @@ module Syctime
|
|
6
8
|
def seconds_to_time(seconds)
|
7
9
|
seconds = seconds.round
|
8
10
|
duration = []
|
9
|
-
duration << seconds % 60
|
10
|
-
duration << seconds / 60 % 60
|
11
|
-
duration << seconds / 60 / 60 %
|
12
|
-
duration << seconds / 60 / 60 /
|
13
|
-
duration << seconds / 60 / 60 /
|
14
|
-
duration << seconds / 60 / 60 /
|
15
|
-
duration << seconds / 60 / 60 /
|
11
|
+
duration << seconds % 60 # seconds
|
12
|
+
duration << seconds / 60 % 60 # minutes
|
13
|
+
duration << seconds / 60 / 60 % 24 # hours
|
14
|
+
duration << seconds / 60 / 60 / 24 % 7 # days
|
15
|
+
duration << seconds / 60 / 60 / 24 / 7 % 4 # weeks
|
16
|
+
duration << seconds / 60 / 60 / 24 / 7 / 4 % 12 # months
|
17
|
+
duration << seconds / 60 / 60 / 24 / 7 / 4 / 12 # years
|
16
18
|
end
|
17
19
|
|
18
20
|
# Translates seconds into a time string like 1 year 2 weeks 5 days 10 minutes.
|
@@ -27,4 +29,41 @@ module Syctime
|
|
27
29
|
time_string
|
28
30
|
end
|
29
31
|
|
32
|
+
# Creates a time string separating hours, minutes and seconds with the
|
33
|
+
# provided separator like 12:50:33
|
34
|
+
def separated_time_string(seconds, separator)
|
35
|
+
secs = seconds % 60
|
36
|
+
mins = seconds / 60 % 60
|
37
|
+
hours = seconds / 60 / 60
|
38
|
+
time_string = sprintf("%02d#{separator}%02d#{separator}%02d", hours, mins, secs)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Translates a time in the ISO 8601 schema to a time object.
|
42
|
+
# 2013-04-09 21:45 -200
|
43
|
+
def time_for_string(time)
|
44
|
+
time = time.scan(/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/)[0].sub(' ','T')
|
45
|
+
Time.xmlschema(time)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Tests whether the date is between from and to. Returns true then otherwise
|
49
|
+
# false. Time, from and to are Time objects as retrieved from Time.now or
|
50
|
+
# Time.local(2013,"apr",13,10,50,0). Alternatively time strings can be
|
51
|
+
# provided in the form of "2013-04-13".
|
52
|
+
def date_between?(date, from, to)
|
53
|
+
date = date.strftime("%Y-%m-%d") if date.class == Time
|
54
|
+
from = from.strftime("%Y-%m-%d") if from.class == Time
|
55
|
+
to = to.strftime("%Y-%m-%d") if to.class == Time
|
56
|
+
time_pattern = /\d{4}-\d{2}-\d{2}/
|
57
|
+
raise ArgumentError if date.scan(time_pattern).empty?
|
58
|
+
raise ArgumentError if from.scan(time_pattern).empty?
|
59
|
+
raise ArgumentError if to.scan(time_pattern).empty?
|
60
|
+
date >= from && date <= to
|
61
|
+
end
|
62
|
+
|
63
|
+
# Checks whether the time is between from and to. Returns true then otherwise
|
64
|
+
# false. time, from and to have to be Time objects.
|
65
|
+
def time_between?(time, from, to)
|
66
|
+
time >= from && time <= to
|
67
|
+
end
|
68
|
+
|
30
69
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'rainbow'
|
5
|
+
|
6
|
+
# ConsoleTimer prints a task and the lead time at the upper right corner of the
|
7
|
+
# schreen. Invokation example:
|
8
|
+
# * Create a semaphore like id.track
|
9
|
+
# * Console time in a new ruby process
|
10
|
+
# semaphore = File.expand_path("~/.syc/syctask/#{id}.track"
|
11
|
+
# FileUtils.touch semaphore
|
12
|
+
# system "ruby lib/sycutil/console_timer.rb 60 10 semaphore"
|
13
|
+
# This will start the ConsoleTimer with a lead time of 1 minute for task 10.
|
14
|
+
# To stop the timer the semaphore has to be deleted
|
15
|
+
# FileUtils.rm semaphore
|
16
|
+
class ConsoleTimer
|
17
|
+
|
18
|
+
# Create a new ConsoleTimer with the time to count down, the task's ID and a
|
19
|
+
# semaphore. The semaphore is a file named id.track where id is equal to the
|
20
|
+
# provided id. The semaphore is checked for existence. If the semaphore is
|
21
|
+
# deleted than ConsoleTimer is stopped.
|
22
|
+
def initialize(time, id, semaphore)
|
23
|
+
@time = time.to_i
|
24
|
+
@id = id
|
25
|
+
@start = Time.now
|
26
|
+
@semaphore = semaphore
|
27
|
+
end
|
28
|
+
|
29
|
+
# Starts the timer. The timer is run as long the semaphore is available
|
30
|
+
def start
|
31
|
+
track = true
|
32
|
+
while track
|
33
|
+
sleep 1
|
34
|
+
output
|
35
|
+
track = File.exists? @semaphore
|
36
|
+
end
|
37
|
+
exit 0
|
38
|
+
end
|
39
|
+
|
40
|
+
# Prints the id and the lead time of the currently tracked task. As long as
|
41
|
+
# the provided time is greater than 0 the time is printed in green, otherwise
|
42
|
+
# red
|
43
|
+
def output
|
44
|
+
color = :green
|
45
|
+
difference = @time - (Time.now - @start).round
|
46
|
+
if difference < 0
|
47
|
+
difference = difference.abs
|
48
|
+
color = :red
|
49
|
+
end
|
50
|
+
seconds = difference % 60
|
51
|
+
minutes = difference / 60 % 60
|
52
|
+
hours = difference / 60 / 60 % 60
|
53
|
+
count_down = sprintf("%d: %02d:%02d:%02d", @id, hours, minutes, seconds)
|
54
|
+
size = count_down.size
|
55
|
+
count_down = count_down.color(color)
|
56
|
+
command = "tput sc;"+
|
57
|
+
"tput cup 0 $(($(tput cols) - #{size}));"+
|
58
|
+
"echo #{count_down};tput rc"
|
59
|
+
system command
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
# Expects to receive parameters duration, id and semaphore
|
65
|
+
if ARGV.size == 3
|
66
|
+
duration = ARGV.shift
|
67
|
+
id = ARGV.shift
|
68
|
+
semaphore = ARGV.shift
|
69
|
+
timer = ConsoleTimer.new(duration, id, semaphore)
|
70
|
+
timer.start
|
71
|
+
else
|
72
|
+
exit -1
|
73
|
+
end
|
74
|
+
|
75
|
+
|