hbtrack 0.0.7 → 0.0.8

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.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hbtrack
4
+ module Importer
5
+ class AbstractImporter
6
+
7
+ def initialize
8
+ @habits = {}
9
+ @entries = {}
10
+ end
11
+
12
+ # Store in database
13
+ def store_in(store)
14
+ ids = {}
15
+ @habits.each do |id, habit|
16
+ ids[id] = store.add_habit(habit)
17
+ end
18
+
19
+ @entries.each do |key, entries|
20
+ id = ids[key]
21
+ entries.each do |entry|
22
+ store.add_entry_of(id, entry)
23
+ end
24
+ end
25
+ end
26
+
27
+ # Import and parse the CSV from Streaks
28
+ def import_from(file)
29
+ raise 'Not implemented'
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hbtrack/importer/abstract_importer'
4
+ require 'hbtrack/database/model'
5
+ require 'date'
6
+
7
+ module Hbtrack
8
+ module Importer
9
+ class HbtrackImporter < AbstractImporter
10
+ Habit = Hbtrack::Database::Habit
11
+ Entry = Hbtrack::Database::Entry
12
+
13
+ ENTRY_TYPE = {
14
+ '0' => 'missed',
15
+ '1' => 'completed',
16
+ ' ' => 'skip'
17
+ }
18
+
19
+ def initialize
20
+ super
21
+ @index = 1
22
+ end
23
+
24
+ # Import and parse the CSV from Streaks
25
+ def import_from(file)
26
+ raise 'File not found' unless File.exist?(file)
27
+ input = File.read(file).split(/\n\n/)
28
+ input.each_with_index do |collection, index|
29
+ extract_from(index, collection)
30
+ end
31
+
32
+ [@habits, @entries]
33
+ end
34
+
35
+ def extract_from(id, collection)
36
+ arr = collection.split("\n")
37
+
38
+ # Get habit name
39
+ habit_name = arr.shift
40
+ @habits[id] = create_habit(habit_name)
41
+
42
+ create_entries_of(id, arr)
43
+ end
44
+
45
+ # Create a Habit
46
+ def create_habit(habit)
47
+ habit = Habit.new(habit, @index)
48
+ @index += 1
49
+ habit
50
+ end
51
+
52
+ def create_entries_of(id, entries)
53
+ @entries[id] = entries.flat_map do |entry|
54
+ month, values = entry.split(': ')
55
+
56
+ values.split("").map.with_index(1) do |value, index|
57
+ create_entry(month, index, value)
58
+ end
59
+ end
60
+ end
61
+
62
+ def create_entry(month, day, value)
63
+ timestamp = create_timestamp_for(month, day)
64
+ type = ENTRY_TYPE[value]
65
+ Entry.new(timestamp, type)
66
+ end
67
+
68
+ def create_timestamp_for(month, day)
69
+ year, month = month.split(',').map(&:to_i)
70
+ time_zone = Time.new.zone
71
+ DateTime.new(year, month, day, 0, 0, 0, "#{time_zone}:00").to_s
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'hbtrack/importer/abstract_importer'
4
+ require 'hbtrack/database/model'
5
+ require 'csv'
6
+
7
+ module Hbtrack
8
+ module Importer
9
+ class StreaksImporter < AbstractImporter
10
+ Habit = Hbtrack::Database::Habit
11
+ Entry = Hbtrack::Database::Entry
12
+
13
+ # Import and parse the CSV from Streaks
14
+ def import_from(file)
15
+ raise 'File not found' unless File.exist?(file)
16
+ CSV.foreach(file, headers: true) do |row|
17
+ extract_streaks_data(row)
18
+ end
19
+ # Handle the parsed data
20
+ [@habits, @entries]
21
+ end
22
+
23
+ private
24
+ # Extract Streaks data from each line
25
+ def extract_streaks_data(line)
26
+ task_id = line.fetch('task_id')
27
+ find_or_create_habit(task_id, line)
28
+ create_entry(task_id, line)
29
+ end
30
+
31
+ # Find or create habit
32
+ def find_or_create_habit(id, line)
33
+ unless @habits.has_key? id
34
+ title = line.fetch('title').strip
35
+ page = line.fetch('page').to_i
36
+ display_order = line.fetch('display_order').to_i
37
+ display_order = page * display_order
38
+ @habits[id] = Habit.new(title, display_order)
39
+ end
40
+ end
41
+
42
+ # Create entry
43
+ def create_entry(task_id, line)
44
+ date = line.fetch('entry_date') # Get Date of entry
45
+ timestamp = line.fetch('entry_timestamp').split("T") # Get Time of entry
46
+ # Create timestamp
47
+ timestamp = DateTime.parse(date + "T" + timestamp[1]).to_s
48
+ type = line.fetch('entry_type')
49
+ @entries[task_id] = [] unless @entries[task_id]
50
+ @entries[task_id] << Entry.new(timestamp, type)
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+
@@ -36,7 +36,7 @@ module Hbtrack
36
36
  # @return [String] formatted result
37
37
  def format(hash)
38
38
  percentage = to_percentage(hash)[:done]
39
- sprintf('Completion rate: %.2f%', percentage)
39
+ sprintf("Completion rate: %.2f%%", percentage)
40
40
  end
41
41
 
42
42
  # Convert the value in the hash into percentage
@@ -4,7 +4,7 @@ module Hbtrack
4
4
  # This class contains the methods that
5
5
  # are used to format the progress of a Habit
6
6
  # into string
7
- class Util
7
+ module Util
8
8
  FONT_COLOR = {
9
9
  green: "\e[32m",
10
10
  red: "\e[31m",
@@ -19,7 +19,7 @@ module Hbtrack
19
19
  value + string + "\e[0m"
20
20
  end
21
21
  end
22
-
22
+
23
23
  # Format the string with title style.
24
24
  #
25
25
  # @param string [String] the string to be styled as title
@@ -54,16 +54,9 @@ module Hbtrack
54
54
  " #{year}" + ' : '
55
55
  end
56
56
 
57
- # Format the current month and year into string
58
- #
59
- # @return [String] Month and Year in String.
60
- #
61
- # == Example
62
- #
63
- # Util.current_month
64
- # #=> "August 2017"
65
- def current_month
66
- Date.today.strftime('%B %Y')
57
+ def get_date_from(key:)
58
+ date_component = key.to_s.split(',').map(&:to_i)
59
+ Date.new(date_component[0], date_component[1], 1)
67
60
  end
68
61
 
69
62
  # Get the month in string form from given key
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Hbtrack
4
- VERSION = '0.0.7'
4
+ VERSION = '0.0.8'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hbtrack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - kw7oe
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-02 00:00:00.000000000 Z
11
+ date: 2018-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,34 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sequel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.4'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.4'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  description: Habit Tracker CLI
56
98
  email:
57
99
  - choongkwern@hotmail.com
@@ -68,21 +110,27 @@ files:
68
110
  - LICENSE.txt
69
111
  - README.md
70
112
  - Rakefile
113
+ - bin/irb
71
114
  - exe/hbtrack
72
115
  - hbtrack.gemspec
73
116
  - lib/hbtrack.rb
117
+ - lib/hbtrack/cli/cli.rb
118
+ - lib/hbtrack/cli/view.rb
74
119
  - lib/hbtrack/command.rb
75
120
  - lib/hbtrack/command/add_command.rb
121
+ - lib/hbtrack/command/import_command.rb
76
122
  - lib/hbtrack/command/list_command.rb
77
123
  - lib/hbtrack/command/remove_command.rb
124
+ - lib/hbtrack/command/show_command.rb
78
125
  - lib/hbtrack/command/update_command.rb
79
126
  - lib/hbtrack/config.rb
127
+ - lib/hbtrack/database/model.rb
128
+ - lib/hbtrack/database/sequel_store.rb
80
129
  - lib/hbtrack/error_handler.rb
81
- - lib/hbtrack/habit.rb
82
- - lib/hbtrack/habit_printer.rb
83
- - lib/hbtrack/habit_tracker.rb
130
+ - lib/hbtrack/importer/abstract_importer.rb
131
+ - lib/hbtrack/importer/hbtrack_importer.rb
132
+ - lib/hbtrack/importer/streaks_importer.rb
84
133
  - lib/hbtrack/stat_formatter.rb
85
- - lib/hbtrack/store.rb
86
134
  - lib/hbtrack/util.rb
87
135
  - lib/hbtrack/version.rb
88
136
  homepage: https://github.com/kw7oe/hbtrack
@@ -105,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
153
  version: '0'
106
154
  requirements: []
107
155
  rubyforge_project:
108
- rubygems_version: 2.6.13
156
+ rubygems_version: 2.7.3
109
157
  signing_key:
110
158
  specification_version: 4
111
159
  summary: A CLI to track your habits.
@@ -1,182 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'date'
4
- require 'hbtrack/util'
5
-
6
- module Hbtrack
7
- # Habit class
8
- class Habit
9
- attr_accessor :name, :progress
10
- # Class Methods
11
-
12
- class << self
13
- # Generate hash key for progress based
14
- # on date.
15
- #
16
- # Example
17
- #
18
- # Habit.get_progress_key_from(Date.new(2017, 7, 18))
19
- # # => :"2017,7"
20
- def get_progress_key_from(date)
21
- date.strftime('%Y,%-m').to_sym
22
- end
23
-
24
- # Initialize Habit object from string.
25
- #
26
- # @param string [String] The string to be parse.
27
- # @return [Habit] a habit object
28
- #
29
- # == Example
30
- #
31
- # Habit.initialize_from_string("workout\n2017,6:1001")
32
- # # => #<Habit:0x007f9be6041b70 @name="workout",
33
- # # @progress={:"2017,6"=>"1001"}>
34
- #
35
- # Habit.initialize_from_string("")
36
- # # => nil
37
- def initialize_from_string(string)
38
- return nil if string.empty?
39
- arr = string.split("\n")
40
- habit_name = arr.shift
41
- hash = {}
42
- arr.each do |s|
43
- a = s.split(': ')
44
- value = a[1] ? a[1] : ''
45
- hash[a[0].to_sym] = value
46
- end
47
- Habit.new(habit_name, hash)
48
- end
49
- end
50
-
51
- def initialize(name,
52
- progress = {
53
- Habit.get_progress_key_from(Date.today) => ''
54
- })
55
- @name = name
56
- @progress = progress
57
- end
58
-
59
- # The length of the habit name.
60
- #
61
- # @return [Numeric] length of the habit name
62
- def name_length
63
- name.length
64
- end
65
-
66
- # Get the latest progress key.
67
- #
68
- # @return [Symbol] latest progress key
69
- def latest_key
70
- key = Habit.get_progress_key_from(Date.today)
71
- initialize_progress_hash_from(key) if progress[key].nil?
72
- key
73
- end
74
-
75
- # Get the latest progress.
76
- #
77
- # @return [String] value of the progress
78
- def latest_progress
79
- progress[latest_key]
80
- end
81
-
82
- # Get the stat for the latest progress.
83
- #
84
- # @return [Hash] stat for the progress.
85
- def latest_stat
86
- stat_for_progress(latest_key)
87
- end
88
-
89
- # Find the month in progress with
90
- # the longest name
91
- #
92
- # @return [String] month
93
- def longest_month
94
- key = progress.keys.max_by do |x|
95
- Util.get_month_from(x).length
96
- end
97
- Util.get_month_from(key)
98
- end
99
-
100
- # Update the status of the progress
101
- #
102
- # @param done [true, false] If true, it is marked as done.
103
- # Else, marked as undone.
104
- # @param date [Date] The date of the progress
105
- # @return [void]
106
- def done(done = true, date = Date.today)
107
- key = Habit.get_progress_key_from(date)
108
- initialize_progress_hash_from(key)
109
- update_progress_for(key, date.day, done)
110
- end
111
-
112
- # TODO: test needed
113
- # Get the done status for specific date
114
- #
115
- # @return [Integer]
116
- def done_for(date:) # TODO: Test needed
117
- latest_progress.split('')[date.day - 1]
118
- end
119
-
120
- # Get the stat of the progress.
121
- #
122
- # @param key [Symbol] key for the progress
123
- # @return [Hash] stat of the progress in the form of
124
- # == Example:
125
- #
126
- # habit.stat_for_progress("2017,5".to_sym)
127
- # # => { done: 5, undone: 2 }
128
- def stat_for_progress(key)
129
- undone = @progress[key].split('').count { |x| x == '0' }
130
- done = @progress[key].split('').count { |x| x == '1' }
131
- { done: done, undone: undone }
132
- end
133
-
134
- # Get all of the progress of the habit in string form
135
- #
136
- # == Example:
137
- #
138
- # habit.progress_output
139
- # # => "2017,5: 0010001010\n2017,6: 000010010\n"
140
- #
141
- def progress_output
142
- arr = @progress.map do |key, value|
143
- "#{key}: #{value}\n"
144
- end
145
- arr.join('')
146
- end
147
-
148
- def overall_stat
149
- done = 0
150
- undone = 0
151
- @progress.each do |key, _value|
152
- stat = stat_for_progress(key)
153
- done += stat[:done]
154
- undone += stat[:undone]
155
- end
156
- { done: done, undone: undone }
157
- end
158
-
159
- def overall_stat_description(formatter)
160
- Util.title('Total') +
161
- formatter.format(overall_stat)
162
- end
163
-
164
- def to_s
165
- "#{name}\n" + progress_output + "\n"
166
- end
167
-
168
- private
169
-
170
- def initialize_progress_hash_from(key)
171
- @progress[key] = '' unless @progress.key? key
172
- end
173
-
174
- def update_progress_for(key, day, done)
175
- i = day - @progress[key].length - 1
176
- result = @progress[key].split('')
177
- i.times { result << ' ' }
178
- result[day - 1] = done ? '1' : '0'
179
- @progress[key] = result.join('')
180
- end
181
- end
182
- end