fbe 0.0.55 → 0.0.56

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 705cf29669f71d490c86421f566b0ec05c61fa1d8352b97d752ea26b8bcbb294
4
- data.tar.gz: e68fc23391048fac0a41a5b26af5ac85c4a34b3c434845710736d093d7eeb714
3
+ metadata.gz: 50405a3f7472db8c909709be30db7a6eed4f5923fca49fac7ac58da9e936c324
4
+ data.tar.gz: 60d9ca2097226f9763e532e0f27f020087994953d772029fb7bfb9570e6c8396
5
5
  SHA512:
6
- metadata.gz: 20ca9dfe05821edf5df55fccc51303fa23598e81dd15361cfb8b8f23db99b399c9e984ed0a1e1e97f43a0ebd048bd0beec5d8f870163cf0cea5c264fc1a505fc
7
- data.tar.gz: e8fdc7f6988f441cf0d0cb63c52f29a95f17c9681be435eb6c57012403e903e0ce65bd4b60402e802485221f3c7d7ca0cc847d1ba2f40e318af9be82ab989dcc
6
+ metadata.gz: 7a4f743d351eb119586a77f6d675f4c311b511bd72823da1b4be71eb4ba5abcd70a22be42c91973835cc3b5451ae8c8bb68015945f1104ef504a23be073c2913
7
+ data.tar.gz: e3dc8bfefcfc1fbcc5519af0961b8aea92c0ea2702e9d348710557e95ccfb8df725e4d350ecb7e11a3cac839893d27c77a709458cc0dab9c29a9a85eb77da5b6
data/.simplecov CHANGED
@@ -36,6 +36,6 @@ else
36
36
  SimpleCov.start do
37
37
  add_filter '/test/'
38
38
  add_filter '/features/'
39
- minimum_coverage 20
39
+ minimum_coverage 15
40
40
  end
41
41
  end
data/Gemfile.lock CHANGED
@@ -11,6 +11,7 @@ PATH
11
11
  faraday-retry (> 0)
12
12
  graphql-client (> 0)
13
13
  judges (> 0)
14
+ liquid (= 5.5.1)
14
15
  loog (> 0)
15
16
  obk (> 0)
16
17
  octokit (> 0)
@@ -54,7 +55,7 @@ GEM
54
55
  ast (2.4.2)
55
56
  backtrace (0.4.0)
56
57
  base64 (0.2.0)
57
- baza.rb (0.0.6)
58
+ baza.rb (0.0.7)
58
59
  backtrace (> 0)
59
60
  faraday (> 0)
60
61
  faraday-http-cache (> 0)
@@ -77,6 +78,9 @@ GEM
77
78
  diff-lcs (1.5.1)
78
79
  docile (1.4.1)
79
80
  drb (2.2.1)
81
+ elapsed (0.0.1)
82
+ loog (> 0)
83
+ tago (> 0)
80
84
  erubi (1.13.0)
81
85
  ethon (0.16.0)
82
86
  ffi (>= 1.15.0)
@@ -121,21 +125,23 @@ GEM
121
125
  reline (>= 0.4.2)
122
126
  iri (0.8.0)
123
127
  json (2.7.2)
124
- judges (0.25.2)
125
- backtrace (~> 0)
126
- baza.rb (~> 0)
128
+ judges (0.26.0)
129
+ backtrace (> 0)
130
+ baza.rb (> 0)
127
131
  concurrent-ruby (~> 1.2)
128
- factbase (~> 0)
132
+ elapsed (> 0)
133
+ factbase (> 0)
129
134
  gli (~> 2.21)
130
- iri (~> 0)
131
- loog (~> 0)
135
+ iri (> 0)
136
+ loog (> 0)
132
137
  moments (~> 0.3)
133
138
  nokogiri (~> 1.10)
134
- others (~> 0)
135
- retries (~> 0)
136
- tago (~> 0)
139
+ others (> 0)
140
+ retries (> 0)
141
+ tago (> 0)
137
142
  typhoeus (~> 1.3)
138
143
  language_server-protocol (3.17.0.3)
144
+ liquid (5.5.1)
139
145
  logger (1.6.0)
140
146
  loofah (2.22.0)
141
147
  crass (~> 1.0.2)
@@ -164,7 +170,7 @@ GEM
164
170
  faraday (>= 1, < 3)
165
171
  sawyer (~> 0.9)
166
172
  others (0.0.3)
167
- parallel (1.26.2)
173
+ parallel (1.26.3)
168
174
  parser (3.3.4.2)
169
175
  ast (~> 2.4.1)
170
176
  racc
@@ -233,7 +239,7 @@ GEM
233
239
  rubocop-ast (>= 1.31.1, < 2.0)
234
240
  ruby-progressbar (~> 1.7)
235
241
  unicode-display_width (>= 2.4.0, < 3.0)
236
- rubocop-ast (1.32.0)
242
+ rubocop-ast (1.32.1)
237
243
  parser (>= 3.3.1.0)
238
244
  rubocop-performance (1.21.1)
239
245
  rubocop (>= 1.48.1, < 2.0)
data/README.md CHANGED
@@ -29,19 +29,23 @@ These tools help manage facts:
29
29
  * `Fbe.overwrite` changes a property in a fact to another value by deleting
30
30
  the fact first, and then creating a new similar fact with all previous
31
31
  properties but one changed.
32
- * `Fbe.pmp` takes a PMP-related property by the area.
33
32
 
34
33
  They help with formatting:
35
34
 
36
35
  * `Fbe.who` formats user name.
37
36
  * `Fbe.issue` formats issue number.
38
- * `Fbe.award` calculates award by the policy.
37
+ * `Fbe.award` calculates award by the bylaw.
39
38
  * `Fbe.sec` formats seconds.
40
39
 
41
40
  They help with external connections:
42
41
 
43
42
  * `Fbe.octo` connects to GitHub API.
44
43
 
44
+ They help with management:
45
+
46
+ * `Fbe.pmp` takes a PMP-related property by the area.
47
+ * `Fbe.bylaws` builds a hash with bylaws.
48
+
45
49
  ## How to contribute
46
50
 
47
51
  Read
@@ -0,0 +1,7 @@
1
+ (award
2
+ (explain "If a branch has a name that doesn\\\'t obey the convention, a penalty is given to the author")
3
+ (aka
4
+ (let fee -12)
5
+ (give fee "as a basis")
6
+ "deduct ${fee} points")
7
+ )
@@ -0,0 +1,7 @@
1
+ (award
2
+ (explain "When a bug is reported and accepted by the team, the reporter gets a bonus")
3
+ (aka
4
+ (let bonus {{ 8 | times: love }})
5
+ (give bonus "as a basis")
6
+ "award ${bonus} points")
7
+ )
@@ -0,0 +1,82 @@
1
+ (award
2
+ (explain "When a code contribution is made, the author gets a bonus")
3
+ (in hoc "the total number of hits-of-code in the contribution")
4
+ (in comments "the total number of comments made by all reviewers")
5
+ (in reviews "the number of reviews provided")
6
+
7
+ (aka
8
+ (let basis {{ 8 | times: love }})
9
+ (give basis "as a basis")
10
+ "award ${basis} points")
11
+
12
+ (aka
13
+ (let hoc_k {{ 0.05 | times: love }})
14
+ (let hoc_threshold 200)
15
+ (let hoc_max 16)
16
+ (let hoc_min 5)
17
+ (set bonus_for_hoc (if (lt hoc hoc_threshold) (times hoc hoc_k) 0))
18
+ (set bonus_for_hoc (between bonus_for_hoc hoc_min hoc_max))
19
+ (give bonus_for_hoc "for the ${hoc} hits-of-code that you wrote")
20
+ "add ${hoc_k} points for each
21
+ [hit-of-code](https://www.yegor256.com/2014/11/14/hits-of-code.html),
22
+ but not more than ${hoc_max} points")
23
+
24
+ (aka
25
+ (let many_hoc_fee {{ 4 | times: anger }})
26
+ (set penalty_for_hoc (if (gte hoc hoc_threshold) (times -1 many_hoc_fee) 0))
27
+ (give penalty_for_hoc "for too many hits-of-code (${hoc} >= ${hoc_threshold})")
28
+ "deduct ${many_hoc_fee} points if more than ${hoc_threshold}
29
+ [hits-of-code](https://www.yegor256.com/2014/11/14/hits-of-code.html)")
30
+
31
+ (aka
32
+ (let many_hoc_fee2 {{ 8 | times: anger }})
33
+ (let hoc_threshold2 800)
34
+ (set penalty_for_hoc2 (if (gte hoc hoc_threshold2) (times -1 many_hoc_fee2) 0))
35
+ (give penalty_for_hoc2 "for way too many hits-of-code (${hoc} >= ${hoc_threshold2})")
36
+ "deduct ${many_hoc_fee2} points if more than ${hoc_threshold2}
37
+ [hits-of-code](https://www.yegor256.com/2014/11/14/hits-of-code.html)")
38
+
39
+ (aka
40
+ (let no_review_fee {{ 8 | times: anger }})
41
+ (set penalty_for_no_review (if (eq reviews 0) (times -1 no_review_fee) 0))
42
+ (give penalty_for_no_review "for the lack of code review")
43
+ "deduct ${no_review_fee} points if there were no code review")
44
+
45
+ (aka
46
+ (let comments_k {{ 0.1 | times: anger }})
47
+ (let comments_max -16)
48
+ (let comments_min -4)
49
+ (set bonus_for_comments (times comments (times -1 comments_k)))
50
+ (set bonus_for_comments (between bonus_for_comments comments_min comments_max))
51
+ (give bonus_for_comments "for too many (${comments}) comments that were made during review")
52
+ "deduct ${comments_k} points for every comment made during review, but not more than ${comments_max} points")
53
+
54
+ (aka
55
+ (let few_comments_fee {{ 2 | times: anger }})
56
+ (let comments_needed 5)
57
+ (set penalty_for_few_comments (if (and (lt comments comments_needed) (not (eq comments 0))) (times -1 few_comments_fee) 0))
58
+ (give penalty_for_few_comments "for very few (${comments}) comments")
59
+ "deduct ${few_comments_fee} points if there were less than ${comments_needed} comments made during review")
60
+
61
+ (aka
62
+ (let silence_fee {{ 8 | times: anger }})
63
+ (set penalty_for_silence (if (eq comments 0) (times -1 silence_fee) 0))
64
+ (give penalty_for_silence "for absolutely no comments posted by reviewers")
65
+ "deduct ${silence_fee} points if there were absolutely no comments made by reviewers during the review")
66
+
67
+ (aka
68
+ (let few_hoc_fee {{ 4 | times: anger }})
69
+ (let hoc_needed 20)
70
+ (set penalty_for_few_hoc (if (lt hoc hoc_needed) (times -1 few_hoc_fee) 0))
71
+ (give penalty_for_few_hoc "for too few (${hoc}) hits-of-code")
72
+ "deduct ${few_hoc_fee} points if you contribute less than ${hoc_needed} hits-of-code")
73
+
74
+ (aka
75
+ (let max 32)
76
+ (set over (if (gt (total) max) (minus max (total)) 0))
77
+ (give over "to not go over the cap")
78
+ (let min 4)
79
+ (set least (if (lt (total) min) (minus min (total)) 0))
80
+ (give least "to give you at least something")
81
+ "make sure the reward is not larger than ${max} points and not smaller than ${min} points")
82
+ )
@@ -0,0 +1,68 @@
1
+ (award
2
+ (explain "An author of every code review gets a bonus")
3
+ (in hoc "the total number of hits-of-code in the contribution")
4
+ (in comments "the total number of comments made by all reviewers")
5
+ (in self "1 if the review was made for their own code contribution, otherwise zero")
6
+
7
+ (aka
8
+ (let basis {{ 4 | times: love }})
9
+ (give basis "as a basis")
10
+ "award ${basis} points")
11
+
12
+ (aka
13
+ (let self_fee {{ 12 | times: anger }})
14
+ (set penalty_for_self_review (if (eq self 1) (times -1 self_fee) 0))
15
+ (give penalty_for_self_review "for reviewing your own contribution (which is a bad idea)")
16
+ "deduct ${self_fee} points if they reviewed their own contribution")
17
+
18
+ (aka
19
+ (let hoc_k {{ 0.01 | times: love }})
20
+ (let hoc_max 16)
21
+ (let hoc_min 5)
22
+ (set bonus_for_hoc (times hoc hoc_k))
23
+ (set bonus_for_hoc (between bonus_for_hoc hoc_min hoc_max))
24
+ (set bonus_for_hoc (if (eq self 1) 0 bonus_for_hoc))
25
+ (give bonus_for_hoc "for the ${hoc} hits-of-code that you reviewed")
26
+ "add ${hoc_k} points for each
27
+ [hit-of-code](https://www.yegor256.com/2014/11/14/hits-of-code.html),
28
+ but not more than ${hoc_max} points")
29
+
30
+ (aka
31
+ (let few_comments_fee {{ 5 | times: anger }})
32
+ (let comments_needed 6)
33
+ (set penalty_for_few_comments (if (and (lt comments comments_needed) (not (eq comments 0))) (times -1 few_comments_fee) 0))
34
+ (give penalty_for_few_comments "for very few (${comments}) comments")
35
+ "deduct ${few_comments_fee} points if there were less than ${comments_needed} comments made during review")
36
+
37
+ (aka
38
+ (let silence_fee {{ 8 | times: anger }})
39
+ (set penalty_for_silence (if (eq comments 0) (times -1 silence_fee) 0))
40
+ (give penalty_for_silence "for absolutely no comments posted")
41
+ "deduct ${silence_fee} points if there were absolutely no comments made during review")
42
+
43
+ (aka
44
+ (let comments_k {{ 0.25 | times: love }})
45
+ (let comments_max 8)
46
+ (let comments_min 5)
47
+ (set bonus_for_comments (times comments comments_k))
48
+ (set bonus_for_comments (between bonus_for_comments comments_min comments_max))
49
+ (set bonus_for_comments (if (eq self 1) 0 bonus_for_comments))
50
+ (give bonus_for_comments "for the ${comments} comment(s) that you have made")
51
+ "add ${comments_k} points for each comment during the review, but not more than ${comments_max} points")
52
+
53
+ (aka
54
+ (let hoc_fee {{ 4 | times: anger }})
55
+ (let hoc_needed 15)
56
+ (set penalty_for_hoc (if (lt hoc hoc_needed) (times -1 hoc_fee) 0))
57
+ (give penalty_for_hoc "for too few (${hoc}) hits-of-code")
58
+ "deduct ${hoc_fee} points if there were less than ${hoc_needed} hits-of-code")
59
+
60
+ (aka
61
+ (let max 32)
62
+ (set over (if (gt (total) max) (minus max (total)) 0))
63
+ (give over "to not go over the cap")
64
+ (let min 4)
65
+ (set least (if (lt (total) min) (minus min (total)) 0))
66
+ (give least "to give you at least something")
67
+ "make sure the reward is not larger than ${max} points and not smaller than ${min} points")
68
+ )
@@ -0,0 +1,7 @@
1
+ (award
2
+ (explain "When an issue is submitted but then rejected by the team, the reporter gets a penalty")
3
+ (aka
4
+ (let fee {{ -8 | times: anger }})
5
+ (give fee "as a basis")
6
+ "deduct ${fee} points")
7
+ )
@@ -0,0 +1,7 @@
1
+ (award
2
+ (explain "When an enhancement is suggested and accepted by the team, the reporter gets a bonus")
3
+ (aka
4
+ (let bonus {{ 8 | times: love }})
5
+ (give bonus "as a basis")
6
+ "award ${bonus} points")
7
+ )
@@ -0,0 +1,29 @@
1
+ (award
2
+ (explain "When a new release is published, everybody who contributed gets a bonus")
3
+ (in hoc "how many hits-of-code are in the release")
4
+ (in contributors "how many people contributed to the release")
5
+ (aka
6
+ (let basis {{ 12 | times: love }})
7
+ (give basis "as a basis")
8
+ "award ${basis} points")
9
+
10
+ (aka
11
+ (let hoc_k {{ 0.005 | times: love }})
12
+ (let hoc_max 24)
13
+ (let hoc_min 4)
14
+ (set b1 (times hoc hoc_k))
15
+ (set b1 (between b1 hoc_min hoc_max))
16
+ (give b1 "for ${hoc} hits-of-code")
17
+ "add ${hoc_k} points for each
18
+ [hit-of-code](https://www.yegor256.com/2014/11/14/hits-of-code.html),
19
+ but not more than ${hoc_max} points")
20
+
21
+ (aka
22
+ (let max 32)
23
+ (set over (if (gt (total) max) (minus max (total)) 0))
24
+ (give over "to not go over the cap")
25
+ (let min 4)
26
+ (set least (if (lt (total) min) (minus min (total)) 0))
27
+ (give least "to give you at least something")
28
+ "make sure the reward is not larger than ${max} points and not smaller than ${min} points")
29
+ )
@@ -0,0 +1,7 @@
1
+ (award
2
+ (explain "When someone pushes directly to the default branch, they get a penalty")
3
+ (aka
4
+ (let fee -16)
5
+ (give fee "as a basis")
6
+ "${fee} points")
7
+ )
@@ -0,0 +1,40 @@
1
+ (award
2
+ (explain "When a bug is resolved, the person who was assigned to it gets a bonus")
3
+ (in hours "how many hours it took to resolve the bug")
4
+ (in self "1 if the bug was reported and resolved by the same person, otherwise zero")
5
+ (set days (div hours 24))
6
+ (aka
7
+ (let basis {{ 8 | times: love }})
8
+ (give basis "as a basis")
9
+ "award ${basis} points")
10
+
11
+ (aka
12
+ (let b1 {{ 4 | times: love }})
13
+ (let hours_threshold 24)
14
+ (set b1 (if (lt hours hours_threshold) b1 0))
15
+ (give b1 "for resolving it in less than ${hours_threshold} hours")
16
+ "add ${b1} points if it was resolved in less than ${hours_threshold} hours")
17
+
18
+ (aka
19
+ (let self_fee {{ 8 | times: anger }})
20
+ (set penalty_for_self (if (eq self 1) (times -1 self_fee) 0))
21
+ (give penalty_for_self "for resolving the bug reported by you earlier")
22
+ "deduct ${self_fee} points if they resolved the bug earlier reported by themselves")
23
+
24
+ (aka
25
+ (let day_fee {{ 0.5 | times: anger }})
26
+ (set b2 (times -1 (times days day_fee)))
27
+ (let days_fee_max -20)
28
+ (set b2 (max b2 days_fee_max))
29
+ (give b2 "for ${days} days of delay")
30
+ "deduct ${day_fee} points for each day of delay, but no more than ${days_fee_max} points")
31
+
32
+ (aka
33
+ (let max 24)
34
+ (set over (if (gt (total) max) (minus max (total)) 0))
35
+ (give over "to not go over the cap")
36
+ (let min 4)
37
+ (set least (if (lt (total) min) (minus min (total)) 0))
38
+ (give least "to give you at least something")
39
+ "make sure the reward is not larger than ${max} points and not smaller than ${min} points")
40
+ )
data/fbe.gemspec CHANGED
@@ -48,6 +48,7 @@ Gem::Specification.new do |s|
48
48
  s.add_dependency 'faraday-retry', '>0'
49
49
  s.add_dependency 'graphql-client', '>0'
50
50
  s.add_dependency 'judges', '>0'
51
+ s.add_dependency 'liquid', '5.5.1'
51
52
  s.add_dependency 'loog', '>0'
52
53
  s.add_dependency 'obk', '>0'
53
54
  s.add_dependency 'octokit', '>0'
data/lib/fbe/award.rb CHANGED
@@ -23,10 +23,11 @@
23
23
  # SOFTWARE.
24
24
 
25
25
  require 'factbase/syntax'
26
+ require_relative 'fb'
26
27
 
27
28
  # A generator of awards.
28
29
  #
29
- # First, you should create a policy, using the same Lisp-ish syntax as
30
+ # First, you should create a bylaw, using the same Lisp-ish syntax as
30
31
  # we use in queries to a Factbase, for example:
31
32
  #
32
33
  # require 'fbe/award'
@@ -38,17 +39,17 @@ require 'factbase/syntax'
38
39
  # puts b.points # how many points to reward, a number
39
40
  # puts b.greeting # how to explain the reward, a text
40
41
  #
41
- # Or else, you can get a policy text:
42
+ # Or else, you can get a bylaw text:
42
43
  #
43
- # p = a.policy
44
- # puts p.markdown # Markdown of the policy
44
+ # p = a.bylaw
45
+ # puts p.markdown # Markdown of the bylaw
45
46
  #
46
47
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
47
48
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
48
49
  # License:: MIT
49
50
  class Fbe::Award
50
51
  # Ctor.
51
- # @param [String] query The query with the policy
52
+ # @param [String] query The query with the bylaw
52
53
  # @param [String] judge The name of the judge
53
54
  def initialize(query = nil, judge: $judge, global: $global, options: $options, loog: $loog)
54
55
  query = Fbe.pmp(fb: Fbe.fb, global:, options:, loog:).hr.send(judge.gsub('-', '_')) if query.nil?
@@ -66,13 +67,13 @@ class Fbe::Award
66
67
  bill
67
68
  end
68
69
 
69
- # Build a policy object from this award query.
70
- # @return [Fbe::Award::Policy] The policy
71
- def policy
70
+ # Build a bylaw object from this award query.
71
+ # @return [Fbe::Award::Bylaw] The bylaw
72
+ def bylaw
72
73
  term = Factbase::Syntax.new(@query, term: Fbe::Award::PTerm).to_term
73
- policy = Policy.new
74
- term.publish_to(policy)
75
- policy
74
+ bylaw = Bylaw.new
75
+ term.publish_to(bylaw)
76
+ bylaw
76
77
  end
77
78
 
78
79
  # A term for bill.
@@ -172,7 +173,7 @@ class Fbe::Award
172
173
  end
173
174
  end
174
175
 
175
- # A term for policy.
176
+ # A term for bylaw.
176
177
  class PTerm
177
178
  def initialize(operator, operands)
178
179
  @op = operator
@@ -220,33 +221,33 @@ class Fbe::Award
220
221
  end
221
222
  end
222
223
 
223
- def publish_to(policy)
224
+ def publish_to(bylaw)
224
225
  case @op
225
226
  when :award
226
227
  @operands.each do |o|
227
- o.publish_to(policy)
228
+ o.publish_to(bylaw)
228
229
  rescue StandardError => e
229
230
  raise "Failure in #{o}: #{e.message}"
230
231
  end
231
232
  when :aka
232
233
  @operands[0..-2].each do |o|
233
- o.publish_to(policy)
234
+ o.publish_to(bylaw)
234
235
  rescue StandardError => e
235
236
  raise "Failure in #{o}: #{e.message}"
236
237
  end
237
- policy.revert(@operands.size - 1)
238
- policy.line(to_p(@operands[@operands.size - 1]))
238
+ bylaw.revert(@operands.size - 1)
239
+ bylaw.line(to_p(@operands[@operands.size - 1]))
239
240
  when :explain
240
- policy.intro(to_p(@operands[0]))
241
+ bylaw.intro(to_p(@operands[0]))
241
242
  when :in
242
- policy.line("assume that #{to_p(@operands[0])} is #{to_p(@operands[1])}")
243
+ bylaw.line("assume that #{to_p(@operands[0])} is #{to_p(@operands[1])}")
243
244
  when :let
244
- policy.line("let #{to_p(@operands[0])} be equal to #{to_p(@operands[1])}")
245
- policy.let(@operands[0], @operands[1])
245
+ bylaw.line("let #{to_p(@operands[0])} be equal to #{to_p(@operands[1])}")
246
+ bylaw.let(@operands[0], @operands[1])
246
247
  when :set
247
- policy.line("set #{to_p(@operands[0])} to #{to_p(@operands[1])}")
248
+ bylaw.line("set #{to_p(@operands[0])} to #{to_p(@operands[1])}")
248
249
  when :give
249
- policy.line("award #{to_p(@operands[0])}")
250
+ bylaw.line("award #{to_p(@operands[0])}")
250
251
  else
251
252
  raise "Unknown term '#{@op}'"
252
253
  end
@@ -316,8 +317,8 @@ class Fbe::Award
316
317
  end
317
318
  end
318
319
 
319
- # A policy.
320
- class Policy
320
+ # A bylaw.
321
+ class Bylaw
321
322
  attr_reader :vars
322
323
 
323
324
  def initialize
data/lib/fbe/bylaws.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2024 Zerocracy
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ require 'liquid'
26
+ require_relative '../fbe'
27
+
28
+ # A generator of policies/bylaws.
29
+ #
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ def Fbe.bylaws(anger: 2, love: 2)
34
+ home = File.join(__dir__, '../../assets/bylaws')
35
+ raise "The directory with templates is absent '#{home}'" unless File.exist?(home)
36
+ Dir[File.join(home, '*.liquid')].to_h do |f|
37
+ formula = Liquid::Template.parse(File.read(f)).render(
38
+ 'anger' => anger, 'love' => love
39
+ )
40
+ [File.basename(f).gsub(/\.liquid$/, ''), formula]
41
+ end
42
+ end
data/lib/fbe/conclude.rb CHANGED
@@ -33,7 +33,7 @@ require_relative 'if_absent'
33
33
  # @param [String] judge The name of the judge, from the +judges+ tool
34
34
  # @param [Hash] global The hash for global caching
35
35
  # @param [Judges::Options] options The options coming from the +judges+ tool
36
- # @param [Loog] logg The logging facility
36
+ # @param [Loog] loog The logging facility
37
37
  def Fbe.conclude(fb: Fbe.fb, judge: $judge, loog: $loog, options: $options, global: $global, &)
38
38
  c = Fbe::Conclude.new(fb:, judge:, loog:, options:, global:)
39
39
  c.instance_eval(&)
@@ -50,7 +50,7 @@ class Fbe::Conclude
50
50
  # @param [String] judge The name of the judge, from the +judges+ tool
51
51
  # @param [Hash] global The hash for global caching
52
52
  # @param [Judges::Options] options The options coming from the +judges+ tool
53
- # @param [Loog] logg The logging facility
53
+ # @param [Loog] loog The logging facility
54
54
  def initialize(fb:, judge:, global:, options:, loog:)
55
55
  @fb = fb
56
56
  @judge = judge
data/lib/fbe/fb.rb CHANGED
@@ -35,7 +35,7 @@ require_relative '../fbe'
35
35
  # @param [Factbase] fb The global factbase provided by the +judges+ tool
36
36
  # @param [Hash] global The hash for global caching
37
37
  # @param [Judges::Options] options The options coming from the +judges+ tool
38
- # @param [Loog] logg The logging facility
38
+ # @param [Loog] loog The logging facility
39
39
  def Fbe.fb(fb: $fb, global: $global, options: $options, loog: $loog)
40
40
  global[:fb] ||=
41
41
  begin
data/lib/fbe/issue.rb CHANGED
@@ -29,7 +29,7 @@ require_relative '../fbe'
29
29
  # @param [Factbase::Fact] fact The fact, where to get the ID of GitHub issue
30
30
  # @param [Judges::Options] options The options coming from the +judges+ tool
31
31
  # @param [Hash] global The hash for global caching
32
- # @param [Loog] logg The logging facility
32
+ # @param [Loog] loog The logging facility
33
33
  def Fbe.issue(fact, options: $options, global: $global, loog: $loog)
34
34
  rid = fact['repository']
35
35
  raise "There is no 'repository' property" if rid.nil?
data/lib/fbe/overwrite.rb CHANGED
@@ -36,7 +36,7 @@ require_relative 'fb'
36
36
  #
37
37
  # @param [Factbase::Fact] fact The fact to modify
38
38
  # @param [String] property The name of the property to set
39
- # @param [Any] vqlue The value to set
39
+ # @param [Any] value The value to set
40
40
  def Fbe.overwrite(fact, property, value, fb: Fbe.fb)
41
41
  raise 'The fact is nil' if fact.nil?
42
42
  raise "The property is not a String but #{property.class} (#{property})" unless property.is_a?(String)
data/lib/fbe/pmp.rb CHANGED
@@ -31,7 +31,7 @@ require_relative '../fbe'
31
31
  # @param [Factbase] fb The factbase
32
32
  # @param [Hash] global The hash for global caching
33
33
  # @param [Judges::Options] options The options coming from the +judges+ tool
34
- # @param [Loog] logg The logging facility
34
+ # @param [Loog] loog The logging facility
35
35
  def Fbe.pmp(fb: Fbe.fb, global: $global, options: $options, loog: $loog)
36
36
  others do |*args1|
37
37
  area = args1.first
data/lib/fbe/regularly.rb CHANGED
@@ -32,7 +32,7 @@ require_relative 'fb'
32
32
  # @param [Integer] p_since_days Since when to collect stats, X days
33
33
  # @param [Factbase] fb The factbase
34
34
  # @param [String] judge The name of the judge, from the +judges+ tool
35
- # @param [Loog] logg The logging facility
35
+ # @param [Loog] loog The logging facility
36
36
  def Fbe.regularly(area, p_every_days, p_since_days = nil, fb: Fbe.fb, judge: $judge, loog: $loog, &)
37
37
  pmp = fb.query("(and (eq what 'pmp') (eq area '#{area}') (exists #{p_every_days}))").each.to_a.first
38
38
  interval = pmp.nil? ? 7 : pmp[p_every_days].first
@@ -32,7 +32,7 @@ require_relative 'overwrite'
32
32
  # @param [Integer] p_every_hours How frequently to run, every X hours
33
33
  # @param [Factbase] fb The factbase
34
34
  # @param [String] judge The name of the judge, from the +judges+ tool
35
- # @param [Loog] logg The logging facility
35
+ # @param [Loog] loog The logging facility
36
36
  def Fbe.repeatedly(area, p_every_hours, fb: Fbe.fb, judge: $judge, loog: $loog, &)
37
37
  pmp = fb.query("(and (eq what 'pmp') (eq area '#{area}') (exists #{p_every_hours}))").each.to_a.first
38
38
  hours = pmp.nil? ? 24 : pmp[p_every_hours].first
data/lib/fbe/who.rb CHANGED
@@ -30,7 +30,7 @@ require_relative '../fbe'
30
30
  # @param [String] prop The property in the fact, with the ID
31
31
  # @param [Judges::Options] options The options coming from the +judges+ tool
32
32
  # @param [Hash] global The hash for global caching
33
- # @param [Loog] logg The logging facility
33
+ # @param [Loog] loog The logging facility
34
34
  def Fbe.who(fact, prop = :who, options: $options, global: $global, loog: $loog)
35
35
  id = fact[prop.to_s]
36
36
  raise "There is no #{prop} property" if id.nil?
data/lib/fbe.rb CHANGED
@@ -27,5 +27,5 @@
27
27
  # License:: MIT
28
28
  module Fbe
29
29
  # Current version of the gem (changed by .rultor.yml on every release)
30
- VERSION = '0.0.55'
30
+ VERSION = '0.0.56'
31
31
  end
@@ -73,7 +73,7 @@ class TestAward < Minitest::Test
73
73
  'bug in 10 (<36) hours',
74
74
  '+30 as a basis'
75
75
  ].each { |t| assert(g.include?(t), g) }
76
- md = a.policy.markdown
76
+ md = a.bylaw.markdown
77
77
  [
78
78
  'First, assume that _hours_ is hours',
79
79
  ', and award _b₂_'
@@ -129,7 +129,7 @@ class TestAward < Minitest::Test
129
129
  '(award (aka (let x 17) (give x "hey") "add ${x} when necessary"))' =>
130
130
  'Just add **17** when necessary'
131
131
  }.each do |q, t|
132
- md = Fbe::Award.new(q).policy.markdown
132
+ md = Fbe::Award.new(q).bylaw.markdown
133
133
  assert(md.include?(t), md)
134
134
  end
135
135
  end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ # MIT License
4
+ #
5
+ # Copyright (c) 2024 Zerocracy
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in all
15
+ # copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ # SOFTWARE.
24
+
25
+ require 'minitest/autorun'
26
+ require 'loog'
27
+ require_relative '../test__helper'
28
+ require_relative '../../lib/fbe/award'
29
+ require_relative '../../lib/fbe/bylaws'
30
+
31
+ # Test.
32
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
33
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
34
+ # License:: MIT
35
+ class TestBylaws < Minitest::Test
36
+ def test_simple
37
+ laws = Fbe.bylaws
38
+ assert(laws.size > 1)
39
+ assert(!laws['published-release-was-rewarded'].nil?)
40
+ end
41
+
42
+ def test_check_all_bills
43
+ awards = {
44
+ 'published-release-was-rewarded' => {
45
+ { hoc: 0, contributors: 1 } => 24,
46
+ { hoc: 10, contributors: 1 } => 24,
47
+ { hoc: 100, contributors: 1 } => 24,
48
+ { hoc: 500, contributors: 1 } => 29,
49
+ { hoc: 1_000, contributors: 1 } => 32,
50
+ { hoc: 10_000, contributors: 1 } => 32,
51
+ { hoc: 30_000, contributors: 1 } => 32
52
+ },
53
+ 'resolved-bug-was-rewarded' => {
54
+ { hours: 1, self: 0 } => 24,
55
+ { hours: 48, self: 0 } => 14,
56
+ { hours: 80, self: 0 } => 13,
57
+ { hours: 300, self: 0 } => 4,
58
+ { hours: 3_000, self: 0 } => 4,
59
+ { hours: 30_000, self: 0 } => 4,
60
+ { hours: 1, self: 1 } => 8
61
+ },
62
+ 'push-to-master-was-punished' => {
63
+ {} => -16
64
+ },
65
+ 'code-review-was-rewarded' => {
66
+ { hoc: 0, comments: 0, self: 0 } => 4,
67
+ { hoc: 3, comments: 0, self: 0 } => 4,
68
+ { hoc: 78, comments: 7, self: 0 } => 8,
69
+ { hoc: 600, comments: 1, self: 0 } => 10,
70
+ { hoc: 500, comments: 40, self: 0 } => 26,
71
+ { hoc: 5_000, comments: 100, self: 0 } => 32,
72
+ { hoc: 100, comments: 50, self: 1 } => 4,
73
+ { hoc: 10_000, comments: 200, self: 1 } => 4
74
+ },
75
+ 'code-contribution-was-rewarded' => {
76
+ { hoc: 0, comments: 0, reviews: 0 } => 4,
77
+ { hoc: 3, comments: 0, reviews: 0 } => 4,
78
+ { hoc: 78, comments: 0, reviews: 0 } => 4,
79
+ { hoc: 78, comments: 1, reviews: 0 } => 4,
80
+ { hoc: 50, comments: 15, reviews: 0 } => 5,
81
+ { hoc: 50, comments: 25, reviews: 0 } => 4,
82
+ { hoc: 180, comments: 7, reviews: 2 } => 32,
83
+ { hoc: 150, comments: 5, reviews: 1 } => 31,
84
+ { hoc: 500, comments: 25, reviews: 2 } => 4,
85
+ { hoc: 99, comments: 6, reviews: 1 } => 26,
86
+ { hoc: 1_500, comments: 3, reviews: 0 } => 4,
87
+ { hoc: 15_000, comments: 40, reviews: 0 } => 4
88
+ },
89
+ 'bug-report-was-rewarded' => {
90
+ {} => 16
91
+ },
92
+ 'enhancement-suggestion-was-rewarded' => {
93
+ {} => 16
94
+ },
95
+ 'dud-was-punished' => {
96
+ {} => -16
97
+ },
98
+ 'bad-branch-name-was-punished' => {
99
+ {} => -12
100
+ }
101
+ }
102
+ awards.each do |title, pairs|
103
+ formula = Fbe.bylaws[title]
104
+ assert(!formula.nil?, title)
105
+ a = Fbe::Award.new(formula)
106
+ help = [
107
+ " #{title}: {\n ",
108
+ pairs.map do |args, _|
109
+ [
110
+ '{',
111
+ args.empty? ? '' : "#{args.map { |k, v| " #{k}: #{v.to_s.gsub(/(?<!^)([0-9]{3})$/, '_\1')}" }.join(',')} ",
112
+ "} => #{a.bill(args).points}"
113
+ ].join
114
+ end.join(",\n "),
115
+ "\n },"
116
+ ].join
117
+ pairs.each do |args, points|
118
+ b = a.bill(args)
119
+ next if b.points == points
120
+ raise \
121
+ "Wrong reward of #{b.points} points from #{title}, " \
122
+ "while #{points} expected (#{args}): #{b.greeting}\n\n#{help}"
123
+ end
124
+ end
125
+ end
126
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fbe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.55
4
+ version: 0.0.56
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-08-18 00:00:00.000000000 Z
11
+ date: 2024-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">"
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: liquid
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '='
144
+ - !ruby/object:Gem::Version
145
+ version: 5.5.1
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '='
151
+ - !ruby/object:Gem::Version
152
+ version: 5.5.1
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: loog
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -236,9 +250,19 @@ files:
236
250
  - LICENSE.txt
237
251
  - README.md
238
252
  - Rakefile
253
+ - assets/bylaws/bad-branch-name-was-punished.liquid
254
+ - assets/bylaws/bug-report-was-rewarded.liquid
255
+ - assets/bylaws/code-contribution-was-rewarded.liquid
256
+ - assets/bylaws/code-review-was-rewarded.liquid
257
+ - assets/bylaws/dud-was-punished.liquid
258
+ - assets/bylaws/enhancement-suggestion-was-rewarded.liquid
259
+ - assets/bylaws/published-release-was-rewarded.liquid
260
+ - assets/bylaws/push-to-master-was-punished.liquid
261
+ - assets/bylaws/resolved-bug-was-rewarded.liquid
239
262
  - fbe.gemspec
240
263
  - lib/fbe.rb
241
264
  - lib/fbe/award.rb
265
+ - lib/fbe/bylaws.rb
242
266
  - lib/fbe/conclude.rb
243
267
  - lib/fbe/copy.rb
244
268
  - lib/fbe/fb.rb
@@ -261,6 +285,7 @@ files:
261
285
  - rules/basic.fe
262
286
  - test/fbe/middleware/test_quota.rb
263
287
  - test/fbe/test_award.rb
288
+ - test/fbe/test_bylaws.rb
264
289
  - test/fbe/test_conclude.rb
265
290
  - test/fbe/test_copy.rb
266
291
  - test/fbe/test_fb.rb