obst 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1ea9ec553aec1048f197a4313bb6f5bdb82767e78fe793764127e1b798ee5b7
4
- data.tar.gz: 8cfa17989074c75b146f5979cd30e33ea05a062cc3e1347efb1677dd6c4c2a44
3
+ metadata.gz: a5789a008e6c945b5ec70d5e7fc26f14ddebde0a68bb7439e1b1d7cb704a430a
4
+ data.tar.gz: c765b723bb0761c7b99511d27138dccb0df126197b1d322fef9a5f8c655dc096
5
5
  SHA512:
6
- metadata.gz: 13b20ea98bc4cedacfee5a11b267f3f2a263fbcadd9d7a3de83061c17af55257701801dca6cabb687236b2c193bd2accfd99d53a9a8ed121471486e6484473c8
7
- data.tar.gz: a2cda68907af8dd8c15f1f31d00afb977e297e3461bf5bbafc7adbccfc9c06801407dd7a68c0898b19a6585e0c8d6ffa86e598e7be2961e09d5a40cb8d1f8df6
6
+ metadata.gz: ea12a1c66ba26cea6744579da6954119bdb9902899e6903430349b36fab3b9ee464b1b0e1acdcd73b6e3e7f364dbdc595f9c115654989a98d1a4cdd440d902c3
7
+ data.tar.gz: 03b54cfde71edf09ffc5629be69633195c6b51ec1ffed1fa7fc132263a644e7cc61342de951ab217eb93e81c692d2de591748350f8f3d84cba9717d6b1edd1f5
data/exe/obst CHANGED
@@ -11,5 +11,9 @@ end
11
11
 
12
12
  obst_md = File.join(path, 'obst.md')
13
13
  File.open(obst_md, 'w') do |f|
14
+ f.puts Obst::Chart::DailyCount.new(C: path).to_s
15
+ f.puts "\n"
16
+ f.puts Obst::Chart::DailyChange.new(C: path).to_s
17
+ f.puts "\n"
14
18
  f.puts Obst::TouchedFiles.new(C: path).to_s
15
19
  end
data/lib/obst/chart.rb ADDED
@@ -0,0 +1,71 @@
1
+ module Obst
2
+ class Chart
3
+ class DailyCount
4
+ def initialize(**opts)
5
+ @daily_gauge = Obst::DailyGauge.new(C: opts[:C]).lazy
6
+ end
7
+
8
+ def to_s
9
+ labels, data = [], []
10
+ @daily_gauge.take(28 * 3).each do |time_count|
11
+ labels << time_count.time.strftime('%F %a')
12
+ data << time_count.count
13
+ end
14
+
15
+ <<~EOF
16
+ # Daily count
17
+
18
+ ```chart
19
+ type: line
20
+ width: 98%
21
+ legendPosition: bottom
22
+ labels: #{labels.reverse!}
23
+ series:
24
+ - title: current #{data[0]}
25
+ data: #{data.reverse!}
26
+ ```
27
+ EOF
28
+ end
29
+ end
30
+
31
+ class DailyChange
32
+ def initialize(**opts)
33
+ @daily = Obst::GroupByDays.new(C: opts[:C]).lazy
34
+ end
35
+
36
+ def to_s
37
+ labels = []
38
+ datas = {a: [], m: [], d: [], nil => []}
39
+
40
+ @daily.take(28 * 3).each do |record|
41
+ labels << record.date_wday
42
+ datas.each_value{ |data| data << 0 }
43
+
44
+ record.file_changes.each_value do |changes|
45
+ datas[changes.final][-1] += 1
46
+ end
47
+ end
48
+
49
+ <<~EOF
50
+ # Daily change
51
+
52
+ ```chart
53
+ type: line
54
+ width: 98%
55
+ legendPosition: bottom
56
+ labels: #{labels.reverse!}
57
+ series:
58
+ - title: del
59
+ data: #{datas[:d].reverse!}
60
+ - title: nil
61
+ data: #{datas[nil].reverse!}
62
+ - title: mod
63
+ data: #{datas[:m].reverse!}
64
+ - title: new
65
+ data: #{datas[:a].reverse!}
66
+ ```
67
+ EOF
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,35 @@
1
+ require "open3"
2
+ require "obst/daily_increment"
3
+
4
+ module Obst
5
+ class DailyGauge
6
+ include Enumerable
7
+
8
+ def initialize(**opts)
9
+ @path = opts[:C] || '.'
10
+ end
11
+
12
+ ONE_DAY = 60 * 60 * 24
13
+ TimeCount = Struct.new(:time, :count)
14
+
15
+ def each(&block)
16
+ return self unless block
17
+
18
+ time = Time.parse(Time.now.strftime('%F'))
19
+ tot = total_now
20
+ block.call(TimeCount.new(time, tot))
21
+
22
+ DailyIncrement.new(C: @path).each do |incr|
23
+ time -= ONE_DAY
24
+ tot -= incr
25
+ block.call(TimeCount.new(time, tot))
26
+ end
27
+ end
28
+
29
+ def total_now
30
+ total = 0
31
+ Open3.pipeline_r(['git', '-C', @path, 'ls-files'], ['wc', '-l']){ |stdout| total = stdout.read.to_i }
32
+ total
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ require "obst/group_by_days"
2
+
3
+ module Obst
4
+ class DailyIncrement
5
+ include Enumerable
6
+
7
+ def initialize(**opts)
8
+ @group_by_day = GroupByDays.new(**opts)
9
+ end
10
+
11
+ def each(&block)
12
+ return self unless block
13
+
14
+ @group_by_day.each do |pack_log_record|
15
+ block.call(pack_log_record.increment)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -28,6 +28,8 @@ module Obst
28
28
  end
29
29
 
30
30
  def each(&block)
31
+ return self unless block
32
+
31
33
  current_time = @timeline.next
32
34
  record = @log.next
33
35
 
data/lib/obst/pack_log.rb CHANGED
@@ -9,7 +9,7 @@ module Obst
9
9
  @time_fix = block
10
10
  end
11
11
 
12
- class Statuses
12
+ class Changes
13
13
  def <<(st)
14
14
  @arr ||= []
15
15
  @arr << st if @arr.last != st
@@ -20,34 +20,48 @@ module Obst
20
20
  end
21
21
 
22
22
  def final
23
- return :d if @arr[0] == :d
24
- return :a if @arr[-1] == :a
25
- :m
23
+ if @arr[0] == :d
24
+ return @arr[-1] == :a ? nil : :d
25
+ end
26
+
27
+ @arr[-1] == :a ? :a : :m
26
28
  end
27
29
  end
28
30
 
29
- Record = Struct.new(:time, :statuses) do
30
- def status_sum
31
- sum = Hash.new{ |h, k| h[k] = 0 }
32
- statuses.each_value do |status|
33
- sum[status.final] += 1
34
- end
35
- sum
31
+ Record = Struct.new(:time, :file_changes) do
32
+ def date_wday
33
+ Time.parse(time).strftime('%F %a')
36
34
  end
37
35
 
38
- def str_status_sum
39
- sb = []
40
- status_sum.each_pair do |st, count|
41
- sb << "#{st}: #{count}"
36
+ def increment
37
+ file_changes.each_value.reduce(0) do |sum, changes|
38
+ sum +=
39
+ case changes.final
40
+ when :a
41
+ 1
42
+ when :d
43
+ -1
44
+ else
45
+ 0
46
+ end
42
47
  end
43
- sb.join(', ')
44
48
  end
45
49
  end
46
50
 
51
+ # yield PackLog::Record(
52
+ # time:Any,
53
+ # file_changes:Hash{
54
+ # name1 => [:m, :a],
55
+ # name2 => [:d, :m],
56
+ # ...
57
+ # }
58
+ # )
47
59
  def each(&block)
60
+ return self unless block
61
+
48
62
  current_time = nil
49
63
  renames = {}
50
- files_in_one_day = Hash.new{ |files, name| files[name] = Statuses.new }
64
+ files_in_one_day = Hash.new{ |files, name| files[name] = Changes.new }
51
65
 
52
66
  @commits.each do |commit|
53
67
  committed_at = @time_fix.call(commit.committed_at)
@@ -4,24 +4,21 @@ module Obst
4
4
  class TouchedFiles
5
5
  def initialize(**opts)
6
6
  @path = opts[:C]
7
- @buffer = []
7
+ @buffer = ["# Touch files in periods\n"]
8
8
  end
9
9
 
10
10
  def to_s
11
11
  last_7_days
12
- @buffer << ''
13
12
  last_4_weeks_without_last_7_days
14
- @buffer << ''
15
13
  last_3_months_without_last_4_weeks
16
14
  @buffer.join("\n")
17
15
  end
18
16
 
19
17
  def last_7_days
20
- @buffer << "# Last 7 days\n"
18
+ @buffer << "- Last 7 days"
21
19
 
22
20
  GroupByDays.new(C: @path).take(7).each do |record|
23
- wday = Time.parse(record.time).strftime('%a')
24
- @buffer << "- #{record.time} #{wday} (#{record.statuses.size})"
21
+ @buffer << "\t- #{record.date_wday} (#{record.file_changes.count})"
25
22
  list_files(record)
26
23
  end
27
24
  end
@@ -29,10 +26,10 @@ module Obst
29
26
  def last_4_weeks_without_last_7_days
30
27
  before = (Time.now - (60 * 60 * 24 * 7)).strftime('%FT23:59:59')
31
28
 
32
- @buffer << "# 3 weeks earlier\n"
29
+ @buffer << "- 1 week ago"
33
30
 
34
- GroupByDays.new(C: @path, before: before, days: 7).take(3).each do |record|
35
- @buffer << "- #{record.time} (#{record.statuses.size})"
31
+ GroupByDays.new(C: @path, before: before, days: 7).take(3).each_with_index do |record, i|
32
+ @buffer << "\t- #{record.time} is #{1+i}.week#{suffix_s(i)}.ago (#{record.file_changes.count})"
36
33
  list_files(record)
37
34
  end
38
35
  end
@@ -40,32 +37,37 @@ module Obst
40
37
  def last_3_months_without_last_4_weeks
41
38
  before = (Time.now - (60 * 60 * 24 * 28)).strftime('%FT23:59:59')
42
39
 
43
- @buffer << "# 1 month earlier\n"
40
+ @buffer << "- 1 month ago"
44
41
 
45
- GroupByDays.new(C: @path, before: before, days: 28).take(2).each do |record|
46
- @buffer << "- #{record.time} (#{record.statuses.size})"
42
+ GroupByDays.new(C: @path, before: before, days: 28).take(2).each_with_index do |record, i|
43
+ @buffer << "\t- #{record.time} is #{1+i}.month#{suffix_s(i)}.ago (#{record.file_changes.count})"
47
44
  list_files(record)
48
45
  end
49
46
  end
50
47
 
51
48
  def list_files(record)
52
49
  group_by_final_status = Hash.new{ |h, k| h[k] = [] }
53
- record.statuses.each_pair{ |name, status| group_by_final_status[status.final] << name }
50
+ record.file_changes.each_pair{ |file, status| group_by_final_status[status.final] << file }
54
51
 
55
52
  [
56
53
  [:new, :a, '#2db7b5'],
57
54
  [:mod, :m, '#d3be03'],
58
- [:del, :d, '#c71585']
55
+ [:del, :d, '#c71585'],
56
+ [:nil, nil, 'grey']
59
57
  ].each do |long, short, color|
60
58
  files = group_by_final_status[short]
61
59
  next if files.empty?
62
60
  inline_str = inline(files)
63
- @buffer << "\t- <font color='#{color}'>#{long} #{files.count}:</font> #{inline_str}"
61
+ @buffer << "\t\t- <font color='#{color}'>#{long} #{files.count}:</font> #{inline_str}"
64
62
  end
65
63
  end
66
64
 
67
65
  def inline(files)
68
66
  files.sort!.map{ |name| "[[#{name}]]" }.join(' / ')
69
67
  end
68
+
69
+ def suffix_s(i)
70
+ i == 0 ? '' : 's'
71
+ end
70
72
  end
71
73
  end
data/lib/obst/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Obst
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.6"
3
3
  end
data/lib/obst.rb CHANGED
@@ -2,6 +2,8 @@ require "obst/version"
2
2
  require "obst/git_log"
3
3
  require "obst/group_by_days"
4
4
  require "obst/touched_files"
5
+ require "obst/daily_gauge"
6
+ require "obst/chart"
5
7
 
6
8
  module Obst
7
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: obst
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - ken
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-26 00:00:00.000000000 Z
11
+ date: 2022-11-27 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -29,6 +29,9 @@ files:
29
29
  - bin/setup
30
30
  - exe/obst
31
31
  - lib/obst.rb
32
+ - lib/obst/chart.rb
33
+ - lib/obst/daily_gauge.rb
34
+ - lib/obst/daily_increment.rb
32
35
  - lib/obst/git_log.rb
33
36
  - lib/obst/group_by_days.rb
34
37
  - lib/obst/pack_log.rb