-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgoal.rb
352 lines (307 loc) · 10.9 KB
/
goal.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# Purpose: To Create Tasks
module SmartGoals
class Goal
# What it has
attr_accessor :description # description : String
attr_accessor :target_date # target_date : Time
attr_accessor :completed # completed : Boolean
attr_accessor :tasks # tasks : Array of Task
attr_accessor :attainable # attainable : String
attr_accessor :relevant # relevant : String
attr_accessor :recurring_schedulers
attr_reader :question # question : Question
# How to describe it
def initialize
@tasks = []
@recurring_schedulers = []
@completed = false # Goal is set to "not completed" upon creation
@question = Question.new
end
# Add new task to list of tasks
def add_task(task)
@tasks << task
end
# Display the current goal
def display_goal
puts "\nYOUR CURRENT GOAL IS: #{self.description}".light_white
if self.target_date
puts "\nTARGET DATE TO REACH YOUR GOAL: #{self.target_date.strftime('%-d %B %Y')}".light_white
end
if self.attainable
puts "\nWHY I CAN ACHIEVE THIS GOAL: #{self.attainable}".light_white
end
if self.relevant
puts "\nWHY THIS GOAL MATTERS: #{self.relevant}".light_white
end
end
# Change color of the text in the table
def generate_color(status)
if status == :completed
:green
elsif status == :failed
:red
else
:yellow
end
end
# Display list of tasks for Terminal Table
def display_tasks(status)
# Create rows array
rows = []
table_title =
case status
when :todo then "Your Tasks To Be Done".colorize(generate_color(status))
when :completed then "Your Completed Tasks".colorize(generate_color(status))
when :failed then "Your Failed Tasks".colorize(generate_color(status))
end
# Check if tasks were created
@tasks
.select {|task| task.status == status }
.each_with_index do |task, index|
# Append tasks to rows array
rows << [
(index + 1).to_s.colorize(generate_color(status)),
task.description.colorize(generate_color(status)),
task.frequency.to_s.gsub('_', ' ').capitalize.colorize(generate_color(status)),
task.target_date ? task.target_date.strftime("%d/%m/%Y %I:%M:%S %p").colorize(generate_color(status)) : ""
] if task.status == status
end
else
# No tasks were created. Just display "No tasks added yet"
rows << ["", "No tasks added yet".light_white]
end
# Create terminal table for tasks
tasks = Terminal::Table.new(
title: table_title,
headings: ['No.'.light_white, 'Description'.light_white, 'Recurring'.light_white, 'Target Date/Time'.light_white],
rows: rows
)
# Display terminal table
puts ""
puts tasks
end
# Display prompt for frequency
def get_frequency
PROMPT.select("\nHow often would you like to do this task?".light_white) do |menu|
menu.choice 'Just once'.light_white, :once
menu.choice 'Every Minute'.light_white, :every_minute
menu.choice 'Hourly'.light_white, :hourly
menu.choice 'Daily'.light_white, :daily
menu.choice 'Weekly'.light_white, :weekly
menu.choice 'Monthly'.light_white, :monthly
menu.choice 'Yearly'.light_white, :yearly
end
end
# Create new tasks
def create_tasks
system "clear"
if CLI.agree("\nWould you like to set tasks now? (y/n)".light_white)
loop do
display_goal
display_tasks(:todo)
task = Task.new
task.description = @question.ask_for_description("\nDescribe your task:".light_white)
task.frequency = get_frequency
task.creation_date = Time.now.getlocal
case task.frequency
when :once
task.target_date = @question.ask_for_target_date("\nWhen do you aim to complete this task by (dd-mm-yyyy)? \nMake sure your timeframe is REALISTIC.".light_white)
else
task.target_date = Helpers.calculate_task_target_date(
task.creation_date,
task.frequency
)
schedule_recurring_task_creation(task)
end
add_task(task)
task.goal = self
task.create_reminder_notification
task.create_failed_notification
system "clear"
display_goal
display_tasks(:todo)
break unless CLI.agree("\nWould you like to set a new task? (yes/no)".light_white)
end
end
end
# Schedule a recurring task
def schedule_recurring_task_creation(task)
recurring_scheduler = Scheduler.new
@recurring_schedulers << recurring_scheduler
recurring_scheduler.schedule.every "#{Helpers.convert_frequency_to_seconds(task.frequency).to_s}s" do
new_task = Task.new
new_task.description = task.description
new_task.frequency = task.frequency
new_task.creation_date = Time.now.getlocal
new_task.target_date = Helpers.calculate_task_target_date(
new_task.creation_date,
new_task.frequency
)
new_task.recurring_scheduler_id = recurring_scheduler.id
new_task.create_reminder_notification
new_task.create_failed_notification
add_task(new_task)
end
end
# Displays the Task Management Menu
def display_task_management_menu
loop do
system "clear"
self.view_tasks
puts ""
choice = PROMPT.select("What would you like to do for your goal?".light_white) do |menu|
menu.choice 'Create New Tasks'.light_white, '1'
menu.choice 'Delete Task'.light_white, '2'
menu.choice 'Mark Tasks Complete'.light_white, '3'
menu.choice 'Back'.light_white, '4'
end
case choice
when '1'
create_tasks
when '2'
delete_task
when '3'
mark_task_complete
when '4'
break
end
end
end
# Prompt for choice on Task Management Menu and Selects that Choice
def get_task_choice(operation)
system "clear"
display_tasks(:completed)
display_tasks(:failed)
if @tasks.empty?
# Check if operation is create
if operation == "create"
create_tasks
else
# Only verify this if it's not a create operation
choice = CLI.agree("You haven't set any tasks yet. Set a task now? (y/n)".light_white)
if choice
create_tasks
end
end
else
todo_tasks = {}
@tasks
.select {|task| task.status == :todo}
.each_with_index do |task, index|
todo_tasks["#{index + 1}. #{task.description}"] = task
end
todo_tasks["#{todo_tasks.length + 1}. Back"] = :back
task = PROMPT.select("\nSelect an ONGOING task to #{operation}:".light_white, todo_tasks)
end
# Return task choice
task
end
# View selected task
def view_tasks
display_goal
display_tasks(:completed)
display_tasks(:failed)
display_tasks(:todo)
end
# Edit selected task
def edit_task
system "clear"
task = get_task_choice("edit")
# If task was set
if task && task != :back
loop do
system "clear"
attributes = {
"Description: #{task.description}": :description,
"Frequency: #{task.frequency}": :frequency,
"Back": :back
}
attribute = PROMPT.select("Select which task attribute to edit".light_white, attributes)
if attribute == :description
# Change the description
task.description = @question.ask_for_description("Enter new description".light_white)
# Cancel notifications
task.cancel_reminder_notification
task.cancel_failed_notification
# Re-create the notification
task.create_reminder_notification
task.create_failed_notification
# Shutdown previous schedule
recurring_scheduler_first =
@recurring_schedulers
.select {|scheduler| scheduler.id == task.recurring_scheduler_id }
.first
recurring_scheduler_first.schedule.shutdown if recurring_scheduler_first
# Reschedule the recurring task creation
schedule_recurring_task_creation(task)
elsif attribute == :frequency
# Change the frequency
frequency = get_frequency
task.frequency = frequency
# Cancel notifications
task.cancel_reminder_notification
task.cancel_failed_notification
# Shutdown previous schedule
recurring_scheduler_first =
@recurring_schedulers
.select {|scheduler| scheduler.id == task.recurring_scheduler_id }
.first
recurring_scheduler_first.schedule.shutdown if recurring_scheduler_first
# Reschedule the recurring task creation
schedule_recurring_task_creation(task)
elsif attribute == :back
break
end
break unless CLI.agree("\nEdit another attribute? (y/n)".light_white)
end
end
end
# Delete selected task
def delete_task
system "clear"
loop do
task = get_task_choice("delete")
# If task was set
if task && task != :back
# Cancel notifications
task.cancel_reminder_notification
task.cancel_failed_notification
# Delete task from array of tasks
@tasks.delete(task)
# If recurring scheduler set, shut it down
recurring_scheduler_first =
@recurring_schedulers
.select {|scheduler| scheduler.id == task.recurring_scheduler_id }
.first
recurring_scheduler_first.schedule.shutdown if recurring_scheduler_first
break unless CLI.agree("\nDelete another task? (y/n)".light_white)
else
# Just go back to menu
break
end
end
end
# Mark task as complete
def mark_task_complete
system "clear"
# If task was set
loop do
task = get_task_choice("mark complete")
if task && task != :back
task.status = :completed
system "clear"
display_tasks(:completed)
display_tasks(:failed)
# Cancel notifications
task.cancel_reminder_notification
task.cancel_failed_notification
puts "Congratulations on completing this task!".light_white
break unless CLI.agree("\nMark another task complete? (y/n)".light_white)
else
break
end
end
end
end
end