vote-schulze 0.3.0 → 0.4.0

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: 399759c49a38c8c50ce051e0a0af472c40b3cc106395a82d7000872a1e869c95
4
- data.tar.gz: b51864add9c71ba7aab3ad2d7e694e18b0ee5e5701f60ebaaf8dd4e8231259a2
3
+ metadata.gz: e2da9c1fc160ba635a97deaf2c56940ff7be7926394ea7ab1d96fb535b997be1
4
+ data.tar.gz: 381d587847112eb9d0262ff89cac9ed50c4bace349bca2a17fb87bf4b382d8c8
5
5
  SHA512:
6
- metadata.gz: e8f5e1965631c33822f42c489c298789330c2d1c3d7c1fec71fccd5a9ed2b5e257b3e43c6bcd231936354770f59138312947756eff990e14fa1230a4869e9ffa
7
- data.tar.gz: b3e2eacd9ba49a3d73175ab92dc2aab0aa557d090d991225b0d174a3065958df17c6ddaf58bffa8243b2ab951620fa2d97823d4c5db17641351cca06aa785ddf
6
+ metadata.gz: 1a2f49b36dda81c9b7e1bf6a1d37e8c6b97a2319576fc04605d86a0a54e44a890f3bb510a15a966840e12dd6283cb3b13142aee5a0c635603dde5fbee6bf4379
7
+ data.tar.gz: 24a4311754fb2d984ca37e482898b4b1668e950f7fd04d9566cf1d2ae0d7d8159df25925dec69c10f6fa7927a15aa03fbe3f606fd3e769f85117fceb9559beb4
@@ -0,0 +1,14 @@
1
+ # https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates
2
+ version: 2
3
+
4
+ updates:
5
+
6
+ - package-ecosystem: bundler
7
+ directory: "/"
8
+ schedule:
9
+ interval: daily # default: 05:00 UTC
10
+
11
+ - package-ecosystem: github-actions
12
+ directory: "/"
13
+ schedule:
14
+ interval: daily # default: 05:00 UTC
@@ -0,0 +1,52 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ pull_request:
9
+ branches:
10
+ - main
11
+ - master
12
+
13
+ jobs:
14
+ test:
15
+ name: '[Test] Ruby ${{matrix.ruby}} | OS ${{matrix.os}}'
16
+ runs-on: ${{ matrix.os }}
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ ruby:
21
+ - '3.2'
22
+ - '3.1'
23
+ - '3.0'
24
+ # JRuby skipped for now until rubocop-rspec/-capybara are split up;
25
+ # @see https://github.com/rubocop/rubocop-rspec/discussions/1440
26
+ # - jruby
27
+ - truffleruby
28
+ os:
29
+ - ubuntu-latest
30
+ - macos-latest
31
+ - windows-latest
32
+ exclude:
33
+ - os: windows-latest
34
+ ruby: truffleruby
35
+ steps:
36
+ - uses: actions/checkout@v3
37
+ - uses: ruby/setup-ruby@v1
38
+ with:
39
+ ruby-version: ${{ matrix.ruby }}
40
+ bundler-cache: true
41
+ - run: bin/rspec
42
+
43
+ lint:
44
+ name: Lint
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v3
48
+ - uses: ruby/setup-ruby@v1
49
+ with:
50
+ ruby-version: '3.0'
51
+ bundler-cache: true
52
+ - run: bin/rubocop
@@ -0,0 +1,21 @@
1
+ # https://github.com/ahmadnassri/action-dependabot-auto-merge
2
+ name: Dependabot Auto Merge
3
+
4
+ on:
5
+ # more info:
6
+ # https://securitylab.github.com/research/github-actions-preventing-pwn-requests
7
+ pull_request_target:
8
+
9
+ jobs:
10
+ approval:
11
+ runs-on: ubuntu-20.04
12
+ if: github.actor == 'dependabot[bot]'
13
+ steps:
14
+ - uses: actions/checkout@v3
15
+ - uses: ahmadnassri/action-dependabot-auto-merge@v2.6
16
+ with:
17
+ target: patch
18
+ # Note: This needs to be a PAT with (public) repo rights,
19
+ # PAT-owning user needs to have write access to this repo
20
+ # (dependabot needs to recognize the comment as coming from an allowed reviewer)
21
+ github-token: ${{ secrets.BOT_TOKEN }}
data/.rubocop.yml CHANGED
@@ -5,14 +5,28 @@ require:
5
5
 
6
6
  AllCops:
7
7
  DisplayCopNames: true
8
- TargetRubyVersion: 2.6
8
+ TargetRubyVersion: 3.0
9
+ NewCops: enable
9
10
 
11
+ Layout/EndOfLine:
12
+ EnforcedStyle: lf
13
+
14
+ Layout/LineLength:
15
+ Max: 120
16
+
17
+ # TODO: Eventually this library should be better documented; sadly it is not yet
18
+ # NOTE: Good first contribution!
10
19
  Style/Documentation:
11
20
  Enabled: false
12
21
 
13
- # Current state is that we prefer the opposite (reduce/inject)
22
+ # I prefer reduce/inject most of the time.
14
23
  Style/EachWithObject:
15
24
  Enabled: false
16
25
 
17
- Layout/LineLength:
18
- Max: 120
26
+ # Sorry, community, but I don't think it's a good choice.
27
+ Style/GlobalStdStream:
28
+ Enabled: false
29
+
30
+ # some rubocop versions report on this, but we don't want to change the code for this;
31
+ Style/ComparableClamp:
32
+ Enabled: false
data/CODE_OF_CONDUCT.md CHANGED
@@ -1,74 +1,129 @@
1
+
1
2
  # Contributor Covenant Code of Conduct
2
3
 
3
4
  ## Our Pledge
4
5
 
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
6
+ We as members, contributors, and leaders pledge to make participation in our
7
+ community a harassment-free experience for everyone, regardless of age, body
8
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
9
+ identity and expression, level of experience, education, socio-economic status,
10
+ nationality, personal appearance, race, religion, or sexual identity
11
+ and orientation.
12
+
13
+ We pledge to act and interact in ways that contribute to an open, welcoming,
14
+ diverse, inclusive, and healthy community.
11
15
 
12
16
  ## Our Standards
13
17
 
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
18
+ Examples of behavior that contributes to a positive environment for our
19
+ community include:
16
20
 
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
21
+ * Demonstrating empathy and kindness toward other people
22
+ * Being respectful of differing opinions, viewpoints, and experiences
23
+ * Giving and gracefully accepting constructive feedback
24
+ * Accepting responsibility and apologizing to those affected by our mistakes,
25
+ and learning from the experience
26
+ * Focusing on what is best not just for us as individuals, but for the
27
+ overall community
22
28
 
23
- Examples of unacceptable behavior by participants include:
29
+ Examples of unacceptable behavior include:
24
30
 
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
31
+ * The use of sexualized language or imagery, and sexual attention or
32
+ advances of any kind
33
+ * Trolling, insulting or derogatory comments, and personal or political attacks
28
34
  * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
35
+ * Publishing others' private information, such as a physical or email
36
+ address, without their explicit permission
31
37
  * Other conduct which could reasonably be considered inappropriate in a
32
38
  professional setting
33
39
 
34
- ## Our Responsibilities
40
+ ## Enforcement Responsibilities
35
41
 
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
42
+ Community leaders are responsible for clarifying and enforcing our standards of
43
+ acceptable behavior and will take appropriate and fair corrective action in
44
+ response to any behavior that they deem inappropriate, threatening, offensive,
45
+ or harmful.
39
46
 
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
47
+ Community leaders have the right and responsibility to remove, edit, or reject
48
+ comments, commits, code, wiki edits, issues, and other contributions that are
49
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
50
+ decisions when appropriate.
45
51
 
46
52
  ## Scope
47
53
 
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
+ This Code of Conduct applies within all community spaces, and also applies when
55
+ an individual is officially representing the community in public spaces.
56
+ Examples of representing our community include using an official e-mail address,
57
+ posting via an official social media account, or acting as an appointed
58
+ representative at an online or offline event.
54
59
 
55
60
  ## Enforcement
56
61
 
57
62
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at asaaki@mannaz.cc. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
+ reported to the community leaders responsible for enforcement at
64
+ `coc-report@mannaz.cc`.
65
+ All complaints will be reviewed and investigated promptly and fairly.
66
+
67
+ All community leaders are obligated to respect the privacy and security of the
68
+ reporter of any incident.
69
+
70
+ ## Enforcement Guidelines
71
+
72
+ Community leaders will follow these Community Impact Guidelines in determining
73
+ the consequences for any action they deem in violation of this Code of Conduct:
74
+
75
+ ### 1. Correction
76
+
77
+ **Community Impact**: Use of inappropriate language or other behavior deemed
78
+ unprofessional or unwelcome in the community.
79
+
80
+ **Consequence**: A private, written warning from community leaders, providing
81
+ clarity around the nature of the violation and an explanation of why the
82
+ behavior was inappropriate. A public apology may be requested.
83
+
84
+ ### 2. Warning
63
85
 
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
86
+ **Community Impact**: A violation through a single incident or series
87
+ of actions.
88
+
89
+ **Consequence**: A warning with consequences for continued behavior. No
90
+ interaction with the people involved, including unsolicited interaction with
91
+ those enforcing the Code of Conduct, for a specified period of time. This
92
+ includes avoiding interactions in community spaces as well as external channels
93
+ like social media. Violating these terms may lead to a temporary or
94
+ permanent ban.
95
+
96
+ ### 3. Temporary Ban
97
+
98
+ **Community Impact**: A serious violation of community standards, including
99
+ sustained inappropriate behavior.
100
+
101
+ **Consequence**: A temporary ban from any sort of interaction or public
102
+ communication with the community for a specified period of time. No public or
103
+ private interaction with the people involved, including unsolicited interaction
104
+ with those enforcing the Code of Conduct, is allowed during this period.
105
+ Violating these terms may lead to a permanent ban.
106
+
107
+ ### 4. Permanent Ban
108
+
109
+ **Community Impact**: Demonstrating a pattern of violation of community
110
+ standards, including sustained inappropriate behavior, harassment of an
111
+ individual, or aggression toward or disparagement of classes of individuals.
112
+
113
+ **Consequence**: A permanent ban from any sort of public interaction within
114
+ the community.
67
115
 
68
116
  ## Attribution
69
117
 
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
118
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119
+ version 2.0, available at
120
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
121
+
122
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct
123
+ enforcement ladder](https://github.com/mozilla/diversity).
124
+
125
+ [homepage]: https://www.contributor-covenant.org
72
126
 
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
127
+ For answers to common questions about this code of conduct, see the FAQ at
128
+ https://www.contributor-covenant.org/faq. Translations are available at
129
+ https://www.contributor-covenant.org/translations.
data/Gemfile.lock CHANGED
@@ -1,60 +1,77 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vote-schulze (0.3.0.pre.dev)
4
+ vote-schulze (0.3.0)
5
+ matrix (>= 0.4.2)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
8
9
  specs:
9
- ast (2.4.0)
10
- diff-lcs (1.3)
11
- jaro_winkler (1.5.4)
12
- parallel (1.19.1)
13
- parser (2.7.0.2)
14
- ast (~> 2.4.0)
15
- rainbow (3.0.0)
16
- rake (10.5.0)
17
- rspec (3.9.0)
18
- rspec-core (~> 3.9.0)
19
- rspec-expectations (~> 3.9.0)
20
- rspec-mocks (~> 3.9.0)
21
- rspec-core (3.9.1)
22
- rspec-support (~> 3.9.1)
23
- rspec-expectations (3.9.0)
10
+ ast (2.4.2)
11
+ diff-lcs (1.5.0)
12
+ json (2.6.3)
13
+ matrix (0.4.2)
14
+ parallel (1.23.0)
15
+ parser (3.2.2.1)
16
+ ast (~> 2.4.1)
17
+ rainbow (3.1.1)
18
+ rake (13.0.6)
19
+ regexp_parser (2.8.0)
20
+ rexml (3.2.5)
21
+ rspec (3.12.0)
22
+ rspec-core (~> 3.12.0)
23
+ rspec-expectations (~> 3.12.0)
24
+ rspec-mocks (~> 3.12.0)
25
+ rspec-core (3.12.2)
26
+ rspec-support (~> 3.12.0)
27
+ rspec-expectations (3.12.3)
24
28
  diff-lcs (>= 1.2.0, < 2.0)
25
- rspec-support (~> 3.9.0)
26
- rspec-mocks (3.9.1)
29
+ rspec-support (~> 3.12.0)
30
+ rspec-mocks (3.12.5)
27
31
  diff-lcs (>= 1.2.0, < 2.0)
28
- rspec-support (~> 3.9.0)
29
- rspec-support (3.9.2)
30
- rubocop (0.79.0)
31
- jaro_winkler (~> 1.5.1)
32
+ rspec-support (~> 3.12.0)
33
+ rspec-support (3.12.0)
34
+ rubocop (1.50.2)
35
+ json (~> 2.3)
32
36
  parallel (~> 1.10)
33
- parser (>= 2.7.0.1)
37
+ parser (>= 3.2.0.0)
34
38
  rainbow (>= 2.2.2, < 4.0)
39
+ regexp_parser (>= 1.8, < 3.0)
40
+ rexml (>= 3.2.5, < 4.0)
41
+ rubocop-ast (>= 1.28.0, < 2.0)
35
42
  ruby-progressbar (~> 1.7)
36
- unicode-display_width (>= 1.4.0, < 1.7)
37
- rubocop-performance (1.5.2)
38
- rubocop (>= 0.71.0)
39
- rubocop-rake (0.5.0)
40
- rubocop
41
- rubocop-rspec (1.37.1)
42
- rubocop (>= 0.68.1)
43
- ruby-progressbar (1.10.1)
44
- unicode-display_width (1.6.1)
43
+ unicode-display_width (>= 2.4.0, < 3.0)
44
+ rubocop-ast (1.28.1)
45
+ parser (>= 3.2.1.0)
46
+ rubocop-capybara (2.18.0)
47
+ rubocop (~> 1.41)
48
+ rubocop-factory_bot (2.22.0)
49
+ rubocop (~> 1.33)
50
+ rubocop-performance (1.10.2)
51
+ rubocop (>= 0.90.0, < 2.0)
52
+ rubocop-ast (>= 0.4.0)
53
+ rubocop-rake (0.6.0)
54
+ rubocop (~> 1.0)
55
+ rubocop-rspec (2.22.0)
56
+ rubocop (~> 1.33)
57
+ rubocop-capybara (~> 2.17)
58
+ rubocop-factory_bot (~> 2.22)
59
+ ruby-progressbar (1.13.0)
60
+ unicode-display_width (2.4.2)
45
61
 
46
62
  PLATFORMS
47
63
  ruby
64
+ x64-mingw32
48
65
 
49
66
  DEPENDENCIES
50
- bundler (~> 1.17)
51
- rake (~> 10.0)
52
- rspec (~> 3.0)
53
- rubocop (~> 0.79)
54
- rubocop-performance (~> 1.5)
55
- rubocop-rake (~> 0.5)
56
- rubocop-rspec (~> 1.37)
67
+ bundler (~> 2.4)
68
+ rake (~> 13.0)
69
+ rspec (~> 3.12)
70
+ rubocop (~> 1.50)
71
+ rubocop-performance (~> 1.10)
72
+ rubocop-rake (~> 0.6)
73
+ rubocop-rspec (~> 2.22)
57
74
  vote-schulze!
58
75
 
59
76
  BUNDLED WITH
60
- 1.17.2
77
+ 2.4.12
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2011 Christoph Grabo
3
+ Copyright (c) 2011—2020 Christoph Grabo
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
- # vote-schulze ![https://travis-ci.com/asaaki/vote-schulze](https://travis-ci.com/asaaki/vote-schulze.svg?branch=master)
1
+ # vote-schulze [![ci](https://github.com/asaaki/vote-schulze/actions/workflows/ci.yml/badge.svg)](https://github.com/asaaki/vote-schulze/actions/workflows/ci.yml)
2
2
 
3
3
  This gem is a Ruby implementation of the Schulze voting method (with help of the Floyd–Warshall algorithm), a type of the Condorcet voting methods.
4
4
 
5
- **Very alpha! Only basic functionality. No tests yet!**
6
-
7
- (If you want to write the tests: fork, write, test, push request - Thanks!)
5
+ **It's usable, but not production grade.**
8
6
 
9
7
  Wikipedia:
10
8
 
@@ -153,7 +151,8 @@ The result strings are always in format `Candidate:Position`, because it's possi
153
151
 
154
152
  ## Contributing
155
153
 
156
- Bug reports and pull requests are welcome on GitHub at https://github.com/asaaki/vote-schulze. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
154
+ Bug reports and pull requests are welcome on GitHub at https://github.com/asaaki/vote-schulze.
155
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
157
156
 
158
157
  ## Code of Conduct
159
158
 
data/bin/rspec CHANGED
@@ -8,14 +8,12 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- require 'pathname'
12
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
- Pathname.new(__FILE__).realpath)
11
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
14
12
 
15
13
  bundle_binstub = File.expand_path('bundle', __dir__)
16
14
 
17
15
  if File.file?(bundle_binstub)
18
- if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
16
+ if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
19
17
  load(bundle_binstub)
20
18
  else
21
19
  abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
data/bin/rubocop CHANGED
@@ -8,14 +8,12 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- require 'pathname'
12
- ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
13
- Pathname.new(__FILE__).realpath)
11
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
14
12
 
15
13
  bundle_binstub = File.expand_path('bundle', __dir__)
16
14
 
17
15
  if File.file?(bundle_binstub)
18
- if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
16
+ if File.read(bundle_binstub, 300).include?('This file was generated by Bundler')
19
17
  load(bundle_binstub)
20
18
  else
21
19
  abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
@@ -0,0 +1,6 @@
1
+ 4
2
+ 3=alpha;charlie;delta;bravo
3
+ 9=bravo;alpha;charlie;delta
4
+ 8=charlie;delta;alpha;bravo
5
+ 5=delta;alpha;bravo;charlie
6
+ 5=delta;bravo;charlie;alpha
@@ -4,20 +4,23 @@ module Vote
4
4
  module Schulze
5
5
  class Basic
6
6
  # All-in-One class method to get a calculated SchulzeBasic object
7
- def self.call(voting_matrix, candidate_count = nil)
8
- new(voting_matrix, candidate_count).call
7
+ def self.call(voting_data, candidate_count = nil)
8
+ new(voting_data, candidate_count).call
9
9
  end
10
10
 
11
11
  attr_reader :voting_matrix, :play_matrix, :result_matrix,
12
- :ranking, :ranking_abc, :candidate_count, :voting_count
12
+ :ranking, :ranking_abc, :candidate_count, :voting_count,
13
+ :candidate_names, :votes
13
14
 
14
- def initialize(voting_matrix, candidate_count = nil)
15
- unless voting_matrix.is_a?(Vote::Schulze::Input)
16
- voting_matrix = Vote::Schulze::Input.new(voting_matrix, candidate_count)
15
+ def initialize(voting_data, candidate_count = nil)
16
+ unless voting_data.is_a?(Vote::Schulze::Input)
17
+ voting_data = Vote::Schulze::Input.new(voting_data, candidate_count)
17
18
  end
18
- @voting_matrix = voting_matrix.voting_matrix
19
- @candidate_count = voting_matrix.candidate_count
20
- @voting_count = voting_matrix.voting_count
19
+ @voting_matrix = voting_data.voting_matrix
20
+ @candidate_count = voting_data.candidate_count
21
+ @voting_count = voting_data.voting_count
22
+ @candidate_names = voting_data.candidate_names
23
+ @votes = voting_data.votes
21
24
  @play_matrix = ::Matrix.scalar(@candidate_count, 0).extend(Vote::Matrix)
22
25
  @result_matrix = ::Matrix.scalar(@candidate_count, 0).extend(Vote::Matrix)
23
26
  end
@@ -71,16 +74,18 @@ module Vote
71
74
  end
72
75
 
73
76
  def calculate_ranking
74
- @ranking = @result_matrix.row_vectors.map { |e| e.inject(0) { |s, v| s + v } }
77
+ @ranking = @result_matrix.row_vectors.map(&:sum)
75
78
  end
76
79
 
77
80
  def calculate_ranking_abc
78
81
  @ranking_abc =
79
82
  @ranking
80
- .map { |e| [e, (@ranking.index(e) + 65).chr] }
83
+ .map.with_index { |e, i| [e, @candidate_names[i]] }
81
84
  .sort
82
85
  .reverse
83
- .map { |e| "#{e[1]}:#{@ranking.max - e[0] + 1}" } # => "letter:int"
86
+ .map do |(idx, name)|
87
+ "#{name.length == 1 ? name.upcase : name}:#{@ranking.max - idx + 1}"
88
+ end
84
89
  end
85
90
  end
86
91
  end
@@ -3,7 +3,8 @@
3
3
  module Vote
4
4
  module Schulze
5
5
  class Input
6
- attr_reader :candidate_count, :voting_count, :voting_matrix
6
+ attr_reader :candidate_count, :voting_count, :voting_matrix,
7
+ :candidate_names, :votes
7
8
 
8
9
  def initialize(voting_data, candidate_count = nil)
9
10
  @voting_data = voting_data
@@ -19,6 +20,7 @@ module Vote
19
20
  end
20
21
 
21
22
  def insert_voting_array(voting_array)
23
+ @votes = voting_array
22
24
  voting_array.each do |vote|
23
25
  @voting_matrix.each_with_index do |_e, x, y|
24
26
  next if x == y
@@ -29,29 +31,31 @@ module Vote
29
31
  @voting_count = voting_array.size
30
32
  end
31
33
 
32
- def insert_voting_string(voting_string) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
34
+ def insert_voting_string(voting_string) # rubocop:todo all
33
35
  voting_array = []
34
36
  voting_string.split(/\n|\n\r|\r/).each do |voter|
35
- voter = voter.split(/=/)
37
+ voter = voter.split('=')
36
38
  vcount = voter.size == 1 ? 1 : voter[0].to_i
37
39
 
38
- vcount.times do
39
- tmp = voter.last.split(/;/)
40
- tmp2 = []
40
+ tmp = voter.last.split(';')
41
+ tmp2 = []
41
42
 
42
- tmp.map! { |e| [e, @candidate_count - tmp.index(e)] }
43
- # find equal-weighted candidates
44
- tmp.map do |e|
45
- if e[0].size > 1
46
- e[0].split(/,/).each do |f|
47
- tmp2 << [f, e[1]]
48
- end
49
- else
50
- tmp2 << e
43
+ tmp.map! { |e| [e, @candidate_count - tmp.index(e)] }
44
+ # find equal-weighted candidates
45
+ tmp.map do |e|
46
+ if e[0].size > 1
47
+ e[0].split(',').each do |f|
48
+ tmp2 << [f, e[1]]
51
49
  end
50
+ else
51
+ tmp2 << e
52
52
  end
53
+ end
53
54
 
54
- voting_array << (tmp2.sort.map { |e| e[1] }) # order, strip & add
55
+ @candidate_names ||= tmp2.map { |e| e[0] }.sort
56
+ vote = tmp2.sort.map { |e| e[1] } # order, strip & add
57
+ vcount.times do
58
+ voting_array << vote
55
59
  end
56
60
  end
57
61
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Vote
4
4
  module Schulze
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
data/vote-schulze.gemspec CHANGED
@@ -25,11 +25,17 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ['lib']
27
27
 
28
- spec.add_development_dependency 'bundler', '~> 1.17'
29
- spec.add_development_dependency 'rake', '~> 10.0'
30
- spec.add_development_dependency 'rspec', '~> 3.0'
31
- spec.add_development_dependency 'rubocop', '~> 0.79'
32
- spec.add_development_dependency 'rubocop-performance', '~> 1.5'
33
- spec.add_development_dependency 'rubocop-rake', '~> 0.5'
34
- spec.add_development_dependency 'rubocop-rspec', '~> 1.37'
28
+ spec.required_ruby_version = '>= 3.0'
29
+
30
+ spec.add_runtime_dependency 'matrix', '>= 0.4.2'
31
+
32
+ spec.add_development_dependency 'bundler', '~> 2.4'
33
+ spec.add_development_dependency 'rake', '~> 13.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.12'
35
+ spec.add_development_dependency 'rubocop', '~> 1.50'
36
+ spec.add_development_dependency 'rubocop-performance', '~> 1.10'
37
+ spec.add_development_dependency 'rubocop-rake', '~> 0.6'
38
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.22'
39
+
40
+ spec.metadata['rubygems_mfa_required'] = 'true'
35
41
  end
metadata CHANGED
@@ -1,113 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vote-schulze
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christoph Grabo
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-04 00:00:00.000000000 Z
11
+ date: 2023-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: matrix
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - "~>"
18
32
  - !ruby/object:Gem::Version
19
- version: '1.17'
33
+ version: '2.4'
20
34
  type: :development
21
35
  prerelease: false
22
36
  version_requirements: !ruby/object:Gem::Requirement
23
37
  requirements:
24
38
  - - "~>"
25
39
  - !ruby/object:Gem::Version
26
- version: '1.17'
40
+ version: '2.4'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '10.0'
47
+ version: '13.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '10.0'
54
+ version: '13.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '3.0'
61
+ version: '3.12'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '3.0'
68
+ version: '3.12'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rubocop
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '0.79'
75
+ version: '1.50'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '0.79'
82
+ version: '1.50'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rubocop-performance
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '1.5'
89
+ version: '1.10'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '1.5'
96
+ version: '1.10'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: rubocop-rake
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '0.5'
103
+ version: '0.6'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: '0.5'
110
+ version: '0.6'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rubocop-rspec
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - "~>"
102
116
  - !ruby/object:Gem::Version
103
- version: '1.37'
117
+ version: '2.22'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
107
121
  requirements:
108
122
  - - "~>"
109
123
  - !ruby/object:Gem::Version
110
- version: '1.37'
124
+ version: '2.22'
111
125
  description: This gem is a Ruby implementation of the Schulze voting method (using
112
126
  Floyd–Warshall algorithm), a type of the Condorcet voting methods.
113
127
  email:
@@ -118,10 +132,12 @@ extensions: []
118
132
  extra_rdoc_files: []
119
133
  files:
120
134
  - ".editorconfig"
135
+ - ".github/dependabot.yml"
136
+ - ".github/workflows/ci.yml"
137
+ - ".github/workflows/dependabot-auto-merge.yml"
121
138
  - ".gitignore"
122
139
  - ".rspec"
123
140
  - ".rubocop.yml"
124
- - ".travis.yml"
125
141
  - CODE_OF_CONDUCT.md
126
142
  - Gemfile
127
143
  - Gemfile.lock
@@ -133,6 +149,7 @@ files:
133
149
  - bin/rubocop
134
150
  - bin/setup
135
151
  - examples/vote4.list
152
+ - examples/vote4names.list
136
153
  - examples/vote6.list
137
154
  - exe/vote-schulze
138
155
  - lib/vote.rb
@@ -146,8 +163,9 @@ files:
146
163
  homepage: https://github.com/asaaki/vote-schulze
147
164
  licenses:
148
165
  - MIT
149
- metadata: {}
150
- post_install_message:
166
+ metadata:
167
+ rubygems_mfa_required: 'true'
168
+ post_install_message:
151
169
  rdoc_options: []
152
170
  require_paths:
153
171
  - lib
@@ -155,15 +173,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
155
173
  requirements:
156
174
  - - ">="
157
175
  - !ruby/object:Gem::Version
158
- version: '0'
176
+ version: '3.0'
159
177
  required_rubygems_version: !ruby/object:Gem::Requirement
160
178
  requirements:
161
179
  - - ">="
162
180
  - !ruby/object:Gem::Version
163
181
  version: '0'
164
182
  requirements: []
165
- rubygems_version: 3.0.3
166
- signing_key:
183
+ rubygems_version: 3.4.12
184
+ signing_key:
167
185
  specification_version: 4
168
186
  summary: Schulze method implementation (a type of the Condorcet method)
169
187
  test_files: []
data/.travis.yml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.6.5
7
- before_install: gem install bundler -v 1.17.2