sapor 0.3.6
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 +7 -0
- data/Area Class Diagram.dia +0 -0
- data/Area Class Diagram.png +0 -0
- data/Class Diagram.dia +0 -0
- data/Class Diagram.png +0 -0
- data/Example-Catalonia.md +361 -0
- data/Example-Flanders.md +486 -0
- data/Example-Greece.md +25 -0
- data/Example-Oslo.md +678 -0
- data/Example-UnitedKingdom-Referendum.md +132 -0
- data/Examples.md +15 -0
- data/LICENSE +674 -0
- data/README.md +103 -0
- data/Rakefile +18 -0
- data/Technical Documentation.md +14 -0
- data/bin/create_installation_package.sh +49 -0
- data/bin/install.sh +45 -0
- data/bin/sapor.rb +24 -0
- data/bin/sapor.sh +106 -0
- data/data/hu/hungary-2014.txt +1680 -0
- data/data/hu/hungary_2014_screen_scraper.rb +48 -0
- data/data/hu/hungary_2014_to_psv.rb +80 -0
- data/data/hu/index-2014.txt +106 -0
- data/data/ie/2016-04-28_general-election-2016-candidate-details-csv_en.csv +552 -0
- data/data/ie/ireland_2016_to_psv.rb +138 -0
- data/data/no/2020-01-01_partifordeling_1_st_2017.csv +335 -0
- data/data/no/norway_2017_to_psv.rb +61 -0
- data/data/pl/2015-gl-lis-okr.csv +42 -0
- data/data/pl/poland_2015_to_psv.rb +79 -0
- data/data/pl/poland_2015_to_psv_with_ko_and_rsw.rb +94 -0
- data/data/pl/poland_2015_to_psv_with_ko_konf_kp_l_and_zp.rb +100 -0
- data/data/pl/poland_2015_to_psv_with_ko_sld_and_wi.rb +92 -0
- data/data/pl/poland_2015_to_psv_with_sld.rb +84 -0
- data/data/pl/poland_2015_to_psv_with_sld_and_wi.rb +85 -0
- data/data/uk/inject_ukip_2015_as_brexit_2019_in_2017.rb +54 -0
- data/data/uk/united_kingdom_2015.txt +651 -0
- data/data/uk/united_kingdom_2015_to_psv.rb +104 -0
- data/data/uk/united_kingdom_2017.txt +651 -0
- data/data/uk/united_kingdom_2017_to_psv.rb +104 -0
- data/data/uk/united_kingdom_2017_to_psv_with_brexit_and_chuk.rb +113 -0
- data/data/uk/united_kingdom_2017_to_psv_with_tig.rb +111 -0
- data/lib/sapor.rb +147 -0
- data/lib/sapor/binomials_cache.rb +45 -0
- data/lib/sapor/combinations_distribution.rb +222 -0
- data/lib/sapor/denominators.rb +67 -0
- data/lib/sapor/dichotomies.rb +138 -0
- data/lib/sapor/dichotomy.rb +164 -0
- data/lib/sapor/first_past_the_post.rb +82 -0
- data/lib/sapor/largest_remainder.rb +118 -0
- data/lib/sapor/log4r_logger.rb +49 -0
- data/lib/sapor/log_facade.rb +40 -0
- data/lib/sapor/many_past_the_post.rb +113 -0
- data/lib/sapor/multi_district_leveled_proportional.rb +64 -0
- data/lib/sapor/multi_district_proportional.rb +123 -0
- data/lib/sapor/multi_district_variable_threshold_proportional.rb +128 -0
- data/lib/sapor/number_formatter.rb +45 -0
- data/lib/sapor/options.rb +73 -0
- data/lib/sapor/poll.rb +282 -0
- data/lib/sapor/polychotomy.rb +200 -0
- data/lib/sapor/pseudorandom_multirange_enumerator.rb +87 -0
- data/lib/sapor/referendum_polychotomy.rb +165 -0
- data/lib/sapor/regional_data/area.rb +100 -0
- data/lib/sapor/regional_data/austria.rb +84 -0
- data/lib/sapor/regional_data/belgium-brussels-2014.psv +46 -0
- data/lib/sapor/regional_data/belgium-brussels-20190526.psv +33 -0
- data/lib/sapor/regional_data/belgium-flanders-2014.psv +80 -0
- data/lib/sapor/regional_data/belgium-flanders-20190526.psv +74 -0
- data/lib/sapor/regional_data/belgium-wallonia-2014.psv +114 -0
- data/lib/sapor/regional_data/belgium-wallonia-20190526.psv +93 -0
- data/lib/sapor/regional_data/belgium.rb +97 -0
- data/lib/sapor/regional_data/belgium_brussels.rb +62 -0
- data/lib/sapor/regional_data/belgium_flanders.rb +64 -0
- data/lib/sapor/regional_data/belgium_wallonia.rb +63 -0
- data/lib/sapor/regional_data/catalonia-2012-2015.psv +100 -0
- data/lib/sapor/regional_data/catalonia-2012.psv +87 -0
- data/lib/sapor/regional_data/catalonia-2015-jxcat.psv +68 -0
- data/lib/sapor/regional_data/catalonia-2015-no-jxsi.psv +68 -0
- data/lib/sapor/regional_data/catalonia-2015.psv +63 -0
- data/lib/sapor/regional_data/catalonia-20171221-with-vox.psv +67 -0
- data/lib/sapor/regional_data/catalonia-20171221.psv +61 -0
- data/lib/sapor/regional_data/catalonia.rb +124 -0
- data/lib/sapor/regional_data/denmark-20150618-with-e-and-p.psv +164 -0
- data/lib/sapor/regional_data/denmark-20150618-with-e.psv +153 -0
- data/lib/sapor/regional_data/denmark-20150618-with-p.psv +153 -0
- data/lib/sapor/regional_data/denmark-20150618.psv +142 -0
- data/lib/sapor/regional_data/denmark.rb +128 -0
- data/lib/sapor/regional_data/denmark_with_e.rb +128 -0
- data/lib/sapor/regional_data/denmark_with_e_and_p.rb +128 -0
- data/lib/sapor/regional_data/denmark_with_p.rb +128 -0
- data/lib/sapor/regional_data/estonia.rb +88 -0
- data/lib/sapor/regional_data/european-union-great-britain-20140522-brexit-chuk.psv +172 -0
- data/lib/sapor/regional_data/european-union-great-britain-20140522.psv +146 -0
- data/lib/sapor/regional_data/european-union-great-britain-20190523.psv +141 -0
- data/lib/sapor/regional_data/european-union-ireland-2014-ia-ri-sd.psv +64 -0
- data/lib/sapor/regional_data/european-union-ireland-2014-ia-sd.psv +60 -0
- data/lib/sapor/regional_data/european-union-ireland-2014-ia.psv +56 -0
- data/lib/sapor/regional_data/european-union-ireland-2014-sd.psv +56 -0
- data/lib/sapor/regional_data/european-union-ireland-2014.psv +50 -0
- data/lib/sapor/regional_data/european-union-ireland-20190524-ia.psv +58 -0
- data/lib/sapor/regional_data/european-union-ireland-20190524.psv +52 -0
- data/lib/sapor/regional_data/european_union_27_austria.rb +76 -0
- data/lib/sapor/regional_data/european_union_27_croatia.rb +83 -0
- data/lib/sapor/regional_data/european_union_27_denmark.rb +77 -0
- data/lib/sapor/regional_data/european_union_27_estonia.rb +74 -0
- data/lib/sapor/regional_data/european_union_27_finland.rb +74 -0
- data/lib/sapor/regional_data/european_union_27_france.rb +84 -0
- data/lib/sapor/regional_data/european_union_27_ireland.rb +96 -0
- data/lib/sapor/regional_data/european_union_27_ireland_with_ia.rb +97 -0
- data/lib/sapor/regional_data/european_union_27_italy.rb +84 -0
- data/lib/sapor/regional_data/european_union_27_netherlands.rb +81 -0
- data/lib/sapor/regional_data/european_union_27_poland.rb +84 -0
- data/lib/sapor/regional_data/european_union_27_romania.rb +78 -0
- data/lib/sapor/regional_data/european_union_27_slovakia.rb +80 -0
- data/lib/sapor/regional_data/european_union_27_spain.rb +82 -0
- data/lib/sapor/regional_data/european_union_27_sweden.rb +76 -0
- data/lib/sapor/regional_data/european_union_austria.rb +76 -0
- data/lib/sapor/regional_data/european_union_bulgaria.rb +82 -0
- data/lib/sapor/regional_data/european_union_croatia.rb +83 -0
- data/lib/sapor/regional_data/european_union_cyprus.rb +72 -0
- data/lib/sapor/regional_data/european_union_czech_republic.rb +82 -0
- data/lib/sapor/regional_data/european_union_denmark.rb +77 -0
- data/lib/sapor/regional_data/european_union_estonia.rb +74 -0
- data/lib/sapor/regional_data/european_union_finland.rb +74 -0
- data/lib/sapor/regional_data/european_union_flanders.rb +74 -0
- data/lib/sapor/regional_data/european_union_france.rb +84 -0
- data/lib/sapor/regional_data/european_union_french_community_of_belgium.rb +73 -0
- data/lib/sapor/regional_data/european_union_germany.rb +86 -0
- data/lib/sapor/regional_data/european_union_great_britain.rb +98 -0
- data/lib/sapor/regional_data/european_union_greece.rb +77 -0
- data/lib/sapor/regional_data/european_union_hungary.rb +76 -0
- data/lib/sapor/regional_data/european_union_ireland.rb +96 -0
- data/lib/sapor/regional_data/european_union_ireland_with_ia.rb +97 -0
- data/lib/sapor/regional_data/european_union_italy.rb +84 -0
- data/lib/sapor/regional_data/european_union_latvia.rb +81 -0
- data/lib/sapor/regional_data/european_union_lithuania.rb +80 -0
- data/lib/sapor/regional_data/european_union_luxembourg.rb +75 -0
- data/lib/sapor/regional_data/european_union_malta.rb +71 -0
- data/lib/sapor/regional_data/european_union_netherlands.rb +81 -0
- data/lib/sapor/regional_data/european_union_northern_ireland.rb +75 -0
- data/lib/sapor/regional_data/european_union_poland.rb +84 -0
- data/lib/sapor/regional_data/european_union_portugal.rb +75 -0
- data/lib/sapor/regional_data/european_union_romania.rb +78 -0
- data/lib/sapor/regional_data/european_union_slovakia.rb +81 -0
- data/lib/sapor/regional_data/european_union_slovenia.rb +85 -0
- data/lib/sapor/regional_data/european_union_spain.rb +82 -0
- data/lib/sapor/regional_data/european_union_sweden.rb +76 -0
- data/lib/sapor/regional_data/finland-20150419-with-sin.psv +224 -0
- data/lib/sapor/regional_data/finland-20150419.psv +212 -0
- data/lib/sapor/regional_data/finland.rb +107 -0
- data/lib/sapor/regional_data/finland_with_sin.rb +107 -0
- data/lib/sapor/regional_data/flanders-2014.psv +96 -0
- data/lib/sapor/regional_data/flanders-20190526.psv +87 -0
- data/lib/sapor/regional_data/flanders.rb +115 -0
- data/lib/sapor/regional_data/france.rb +38 -0
- data/lib/sapor/regional_data/greece.rb +92 -0
- data/lib/sapor/regional_data/hungary-2014.psv +2104 -0
- data/lib/sapor/regional_data/hungary.rb +116 -0
- data/lib/sapor/regional_data/iceland-20161029-midflokkurinn.psv +94 -0
- data/lib/sapor/regional_data/iceland-20161029.psv +88 -0
- data/lib/sapor/regional_data/iceland-20171028-with-j.psv +94 -0
- data/lib/sapor/regional_data/iceland-20171028.psv +85 -0
- data/lib/sapor/regional_data/iceland.rb +149 -0
- data/lib/sapor/regional_data/ireland-20160226-2020-candidates.psv +322 -0
- data/lib/sapor/regional_data/ireland-20160226-2020.psv +344 -0
- data/lib/sapor/regional_data/ireland-20160226.psv +348 -0
- data/lib/sapor/regional_data/ireland.rb +165 -0
- data/lib/sapor/regional_data/latvia-20141004-kpv-p-par.psv +109 -0
- data/lib/sapor/regional_data/latvia-20141004-kpv-par.psv +103 -0
- data/lib/sapor/regional_data/latvia-20141004-kpv.psv +97 -0
- data/lib/sapor/regional_data/latvia-20141004.psv +89 -0
- data/lib/sapor/regional_data/latvia-20181006.psv +104 -0
- data/lib/sapor/regional_data/latvia.rb +111 -0
- data/lib/sapor/regional_data/luxembourg-20131020.psv +60 -0
- data/lib/sapor/regional_data/luxembourg-20181014.psv +59 -0
- data/lib/sapor/regional_data/luxembourg.rb +88 -0
- data/lib/sapor/regional_data/netherlands.rb +108 -0
- data/lib/sapor/regional_data/norway-20170911.psv +331 -0
- data/lib/sapor/regional_data/norway.rb +130 -0
- data/lib/sapor/regional_data/norwegian_municipality.rb +68 -0
- data/lib/sapor/regional_data/poland-20151025-with-ko-and-l-without-n-po-r-and-zl.psv +321 -0
- data/lib/sapor/regional_data/poland-20151025-with-ko-konf-kp-l-and-zp-without-k-k15-n-pis-po-psl-r-and-zl.psv +280 -0
- data/lib/sapor/regional_data/poland-20151025-with-ko-sld-and-wi-without-n-po-and-zl.psv +403 -0
- data/lib/sapor/regional_data/poland-20151025-with-sld-and-wi-without-zl.psv +444 -0
- data/lib/sapor/regional_data/poland-20151025-with-sld-without-zl.psv +403 -0
- data/lib/sapor/regional_data/poland-20151025.psv +403 -0
- data/lib/sapor/regional_data/poland.rb +125 -0
- data/lib/sapor/regional_data/poland_with_ko_and_l_without_n_po_r_and_zl.rb +122 -0
- data/lib/sapor/regional_data/poland_with_ko_konf_kp_l_and_zp_without_k_k15_n_pis_po_psl_r_and_zl.rb +123 -0
- data/lib/sapor/regional_data/poland_with_ko_sld_and_wi_without_n_po_and_zl.rb +125 -0
- data/lib/sapor/regional_data/poland_with_sld_and_wi_without_zl.rb +126 -0
- data/lib/sapor/regional_data/poland_with_sld_without_zl.rb +126 -0
- data/lib/sapor/regional_data/portugal-20151004-with-a-and-ch-without-paf.psv +438 -0
- data/lib/sapor/regional_data/portugal-20151004-with-a-and-il-without-paf.psv +438 -0
- data/lib/sapor/regional_data/portugal-20151004-with-a-ch-and-il-without-paf.psv +461 -0
- data/lib/sapor/regional_data/portugal-20151004-with-a-without-paf.psv +415 -0
- data/lib/sapor/regional_data/portugal-20151004-with-ch-and-il-without-paf.psv +438 -0
- data/lib/sapor/regional_data/portugal-20151004-without-paf.psv +392 -0
- data/lib/sapor/regional_data/portugal-20151004.psv +370 -0
- data/lib/sapor/regional_data/portugal.rb +101 -0
- data/lib/sapor/regional_data/portugal_with_a_and_ch_without_paf.rb +92 -0
- data/lib/sapor/regional_data/portugal_with_a_and_il_without_paf.rb +92 -0
- data/lib/sapor/regional_data/portugal_with_a_ch_and_il_without_paf.rb +92 -0
- data/lib/sapor/regional_data/portugal_with_a_without_paf.rb +92 -0
- data/lib/sapor/regional_data/portugal_with_ch_and_il_without_paf.rb +92 -0
- data/lib/sapor/regional_data/portugal_without_paf.rb +92 -0
- data/lib/sapor/regional_data/slovakia.rb +81 -0
- data/lib/sapor/regional_data/slovenia.rb +114 -0
- data/lib/sapor/regional_data/spain-20160626.psv +619 -0
- data/lib/sapor/regional_data/spain.rb +136 -0
- data/lib/sapor/regional_data/sweden.rb +92 -0
- data/lib/sapor/regional_data/sweden_20140914.rb +89 -0
- data/lib/sapor/regional_data/united_kingdom-2015.psv +4358 -0
- data/lib/sapor/regional_data/united_kingdom-20170608-brexit-chuk.psv +5154 -0
- data/lib/sapor/regional_data/united_kingdom-20170608-brexit.psv +4521 -0
- data/lib/sapor/regional_data/united_kingdom-20170608-tig.psv +4529 -0
- data/lib/sapor/regional_data/united_kingdom-20170608.psv +3894 -0
- data/lib/sapor/regional_data/united_kingdom.rb +94 -0
- data/lib/sapor/regional_data/united_kingdom_with_brexit.rb +110 -0
- data/lib/sapor/regional_data/united_kingdom_with_brexit_and_chuk.rb +111 -0
- data/lib/sapor/regional_data/united_kingdom_with_tig.rb +111 -0
- data/lib/sapor/regional_data/utopia.rb +66 -0
- data/lib/sapor/regional_data/wallonia-2014.psv +101 -0
- data/lib/sapor/regional_data/wallonia-20190526.psv +88 -0
- data/lib/sapor/regional_data/wallonia.rb +112 -0
- data/lib/sapor/representatives_polychotomy.rb +338 -0
- data/lib/sapor/single_district_proportional.rb +75 -0
- data/sapor.gemspec +35 -0
- data/spec/integration/area_spec.rb +28 -0
- data/spec/integration/poll_spec.rb +112 -0
- data/spec/integration/sample.poll +8 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/unit/area_spec.rb +115 -0
- data/spec/unit/austria_spec.rb +76 -0
- data/spec/unit/belgium_brussels_spec.rb +58 -0
- data/spec/unit/belgium_flanders_spec.rb +62 -0
- data/spec/unit/belgium_spec.rb +26 -0
- data/spec/unit/belgium_wallonia_spec.rb +65 -0
- data/spec/unit/binomials_cache_spec.rb +34 -0
- data/spec/unit/catalonia_spec.rb +61 -0
- data/spec/unit/catalonia_with_vox_spec.rb +62 -0
- data/spec/unit/combinations_distribution_spec.rb +241 -0
- data/spec/unit/denmark_spec.rb +56 -0
- data/spec/unit/denmark_with_e_and_p_spec.rb +58 -0
- data/spec/unit/denmark_with_e_spec.rb +57 -0
- data/spec/unit/denmark_with_p_spec.rb +57 -0
- data/spec/unit/denominators_spec.rb +40 -0
- data/spec/unit/dichotomies_spec.rb +154 -0
- data/spec/unit/dichotomy_spec.rb +320 -0
- data/spec/unit/estonia_spec.rb +65 -0
- data/spec/unit/european_union_27_austria_spec.rb +61 -0
- data/spec/unit/european_union_27_croatia_spec.rb +60 -0
- data/spec/unit/european_union_27_denmark_spec.rb +62 -0
- data/spec/unit/european_union_27_estonia_spec.rb +94 -0
- data/spec/unit/european_union_27_finland_spec.rb +75 -0
- data/spec/unit/european_union_27_france_spec.rb +73 -0
- data/spec/unit/european_union_27_ireland_spec.rb +72 -0
- data/spec/unit/european_union_27_ireland_with_ia_spec.rb +74 -0
- data/spec/unit/european_union_27_italy_spec.rb +69 -0
- data/spec/unit/european_union_27_netherlands_spec.rb +81 -0
- data/spec/unit/european_union_27_poland_spec.rb +69 -0
- data/spec/unit/european_union_27_romania_spec.rb +67 -0
- data/spec/unit/european_union_27_slovakia_spec.rb +111 -0
- data/spec/unit/european_union_27_spain_spec.rb +130 -0
- data/spec/unit/european_union_27_sweden_spec.rb +89 -0
- data/spec/unit/european_union_austria_spec.rb +61 -0
- data/spec/unit/european_union_bulgaria_spec.rb +97 -0
- data/spec/unit/european_union_croatia_spec.rb +59 -0
- data/spec/unit/european_union_cyprus_spec.rb +65 -0
- data/spec/unit/european_union_czech_republic_spec.rb +125 -0
- data/spec/unit/european_union_denmark_spec.rb +61 -0
- data/spec/unit/european_union_estonia_spec.rb +93 -0
- data/spec/unit/european_union_finland_spec.rb +75 -0
- data/spec/unit/european_union_flanders_spec.rb +56 -0
- data/spec/unit/european_union_france_spec.rb +73 -0
- data/spec/unit/european_union_french_community_of_belgium_spec.rb +61 -0
- data/spec/unit/european_union_germany_spec.rb +90 -0
- data/spec/unit/european_union_great_britain_spec.rb +87 -0
- data/spec/unit/european_union_greece_spec.rb +148 -0
- data/spec/unit/european_union_hungary_spec.rb +57 -0
- data/spec/unit/european_union_ireland_spec.rb +72 -0
- data/spec/unit/european_union_ireland_with_ia_spec.rb +74 -0
- data/spec/unit/european_union_italy_spec.rb +69 -0
- data/spec/unit/european_union_latvia_spec.rb +76 -0
- data/spec/unit/european_union_lithuania_spec.rb +68 -0
- data/spec/unit/european_union_luxembourg_spec.rb +63 -0
- data/spec/unit/european_union_malta_spec.rb +60 -0
- data/spec/unit/european_union_netherlands_spec.rb +81 -0
- data/spec/unit/european_union_northern_ireland_spec.rb +66 -0
- data/spec/unit/european_union_poland_spec.rb +69 -0
- data/spec/unit/european_union_portugal_spec.rb +77 -0
- data/spec/unit/european_union_romania_spec.rb +67 -0
- data/spec/unit/european_union_slovakia_spec.rb +111 -0
- data/spec/unit/european_union_slovenia_spec.rb +77 -0
- data/spec/unit/european_union_spain_spec.rb +129 -0
- data/spec/unit/european_union_sweden_spec.rb +89 -0
- data/spec/unit/finland_spec.rb +65 -0
- data/spec/unit/finland_with_sin_spec.rb +67 -0
- data/spec/unit/first_past_the_post_spec.rb +54 -0
- data/spec/unit/flanders_spec.rb +70 -0
- data/spec/unit/france_spec.rb +32 -0
- data/spec/unit/greece_spec.rb +118 -0
- data/spec/unit/hungary_spec.rb +132 -0
- data/spec/unit/iceland_spec.rb +57 -0
- data/spec/unit/iceland_with_j_spec.rb +58 -0
- data/spec/unit/ireland_2016_spec.rb +62 -0
- data/spec/unit/ireland_spec.rb +62 -0
- data/spec/unit/largest_remainder_spec.rb +79 -0
- data/spec/unit/latvia_spec.rb +62 -0
- data/spec/unit/luxembourg_spec.rb +55 -0
- data/spec/unit/multi_district_leveled_proportional_spec.rb +49 -0
- data/spec/unit/multi_district_proportional_spec.rb +81 -0
- data/spec/unit/netherlands_spec.rb +107 -0
- data/spec/unit/norway_spec.rb +69 -0
- data/spec/unit/norwegian_municipality_spec.rb +89 -0
- data/spec/unit/number_formatter_spec.rb +173 -0
- data/spec/unit/poland_spec.rb +62 -0
- data/spec/unit/poland_with_ko_and_l_without_n_po_r_and_zl_spec.rb +60 -0
- data/spec/unit/poland_with_ko_konf_kp_l_and_zp_without_k_k15_n_pis_po_psl_r_and_zl_spec.rb +59 -0
- data/spec/unit/poland_with_ko_sld_and_wi_without_n_po_and_zl_spec.rb +62 -0
- data/spec/unit/poland_with_sld_and_wi_without_zl_spec.rb +63 -0
- data/spec/unit/poland_with_sld_without_zl_spec.rb +62 -0
- data/spec/unit/poll_spec.rb +110 -0
- data/spec/unit/portugal_spec.rb +66 -0
- data/spec/unit/portugal_with_a_and_ch_without_paf_spec.rb +68 -0
- data/spec/unit/portugal_with_a_and_il_without_paf_spec.rb +68 -0
- data/spec/unit/portugal_with_a_ch_and_il_without_paf_spec.rb +69 -0
- data/spec/unit/portugal_with_a_without_paf_spec.rb +67 -0
- data/spec/unit/portugal_with_ch_and_il_without_paf_spec.rb +68 -0
- data/spec/unit/portugal_without_paf_spec.rb +66 -0
- data/spec/unit/pseudorandom_multirange_enumerator_spec.rb +82 -0
- data/spec/unit/referendum_polychotomy_spec.rb +289 -0
- data/spec/unit/representatives_polychotomy_spec.rb +332 -0
- data/spec/unit/slovakia_spec.rb +99 -0
- data/spec/unit/slovenia_spec.rb +80 -0
- data/spec/unit/spain_spec.rb +101 -0
- data/spec/unit/sweden_20140914_spec.rb +112 -0
- data/spec/unit/sweden_spec.rb +113 -0
- data/spec/unit/united_kingdom_spec.rb +65 -0
- data/spec/unit/united_kingdom_with_brexit_and_chuk_spec.rb +67 -0
- data/spec/unit/united_kingdom_with_brexit_spec.rb +66 -0
- data/spec/unit/united_kingdom_with_tig_spec.rb +66 -0
- data/spec/unit/wallonia_spec.rb +70 -0
- metadata +502 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2020 Filip van Laenen <f.a.vanlaenen@ieee.org>
|
|
4
|
+
#
|
|
5
|
+
# This file is part of SAPoR.
|
|
6
|
+
#
|
|
7
|
+
# SAPoR is free software: you can redistribute it and/or modify it under the
|
|
8
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
9
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
10
|
+
# version.
|
|
11
|
+
#
|
|
12
|
+
# SAPoR is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
13
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
14
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You can find a copy of the GNU General Public License in /doc/gpl.txt
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Sapor
|
|
20
|
+
#
|
|
21
|
+
# Class representing an electoral system with more than one
|
|
22
|
+
# district where parties only have a limited number of candidates in each of
|
|
23
|
+
# the constituencies.
|
|
24
|
+
#
|
|
25
|
+
class ManyPastThePost
|
|
26
|
+
def initialize(last_election_result, last_detailed_election_result,
|
|
27
|
+
seat_distribution, caps = {}, weights = {})
|
|
28
|
+
@last_election_result = last_election_result
|
|
29
|
+
@last_detailed_election_result = last_detailed_election_result
|
|
30
|
+
@seat_distribution = seat_distribution
|
|
31
|
+
@caps = caps
|
|
32
|
+
@weights = weights
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def project(simulation)
|
|
36
|
+
multiplicators = calculate_multiplicators(simulation)
|
|
37
|
+
result = create_empty_result(simulation)
|
|
38
|
+
@last_detailed_election_result.each_pair do |name, local_last_result|
|
|
39
|
+
no_of_seats = @seat_distribution[name]
|
|
40
|
+
caps = @caps.empty? ? {} : @caps[name]
|
|
41
|
+
seats = local_seats(no_of_seats, local_last_result, multiplicators,
|
|
42
|
+
caps, @weights)
|
|
43
|
+
add_seats_to_result(result, seats)
|
|
44
|
+
end
|
|
45
|
+
result
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def add_seats_to_result(result, seats)
|
|
51
|
+
seats.each do |seat|
|
|
52
|
+
if result.key?(seat)
|
|
53
|
+
result[seat] += 1
|
|
54
|
+
else
|
|
55
|
+
result[seat] = 1
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def calculate_multiplicators(simulation)
|
|
61
|
+
simulation_sum = simulation.values.inject(:+)
|
|
62
|
+
last_election_sum = @last_election_result.values.inject(:+)
|
|
63
|
+
multiplicators = {}
|
|
64
|
+
simulation.each_key do |choice|
|
|
65
|
+
new_fraction = simulation[choice].to_f / simulation_sum
|
|
66
|
+
last_fraction = @last_election_result[choice].to_f / last_election_sum
|
|
67
|
+
multiplicators[choice] = new_fraction / last_fraction
|
|
68
|
+
end
|
|
69
|
+
multiplicators
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def create_empty_result(simulation)
|
|
73
|
+
result = {}
|
|
74
|
+
simulation.each_key do |choice|
|
|
75
|
+
result[choice] = 0
|
|
76
|
+
end
|
|
77
|
+
result[OTHER] = 0
|
|
78
|
+
result
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def local_votes(local_last_result, multiplicators)
|
|
82
|
+
local_votes = {}
|
|
83
|
+
local_last_result.each_pair do |choice, votes|
|
|
84
|
+
local_votes[choice] = if multiplicators.key?(choice)
|
|
85
|
+
votes * multiplicators[choice]
|
|
86
|
+
else
|
|
87
|
+
votes
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
local_votes
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def local_quotients(local_votes, no_of_seats, caps, weights)
|
|
94
|
+
local_quotients = []
|
|
95
|
+
local_votes.each_pair do |choice, new_value|
|
|
96
|
+
actual_no_of_seats = caps.empty? ? no_of_seats : [caps[choice], no_of_seats].min
|
|
97
|
+
actual_weights = weights[actual_no_of_seats - 1]
|
|
98
|
+
actual_weights.each do |w|
|
|
99
|
+
local_quotients << [choice, new_value.to_f * w]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
local_quotients
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def local_seats(no_of_seats, local_last_result, multiplicators, caps,
|
|
106
|
+
weights)
|
|
107
|
+
local_votes = local_votes(local_last_result, multiplicators)
|
|
108
|
+
local_quotients = local_quotients(local_votes, no_of_seats, caps, weights)
|
|
109
|
+
sorted_quotients = local_quotients.sort { |a, b| b.last <=> a.last }
|
|
110
|
+
sorted_quotients.map(&:first).slice(0, no_of_seats)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
4
|
+
# Copyright (C) 2020 Filip van Laenen <f.a.vanlaenen@ieee.org>
|
|
5
|
+
#
|
|
6
|
+
# This file is part of SAPoR.
|
|
7
|
+
#
|
|
8
|
+
# SAPoR is free software: you can redistribute it and/or modify it under the
|
|
9
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
10
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
11
|
+
# version.
|
|
12
|
+
#
|
|
13
|
+
# SAPoR is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
14
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
15
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You can find a copy of the GNU General Public License in /doc/gpl.txt
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Sapor
|
|
21
|
+
#
|
|
22
|
+
# Class representing a multi-district proportional electoral system with a
|
|
23
|
+
# second round of leveling seats.
|
|
24
|
+
#
|
|
25
|
+
class MultiDistrictLeveledProportional
|
|
26
|
+
def initialize(last_election_result, last_detailed_election_result,
|
|
27
|
+
seat_distribution, leveling_seats, leveling_threshold,
|
|
28
|
+
denominators_class)
|
|
29
|
+
@proportional = MultiDistrictProportional.new(last_election_result,
|
|
30
|
+
last_detailed_election_result,
|
|
31
|
+
seat_distribution, denominators_class)
|
|
32
|
+
@leveling_seats = leveling_seats
|
|
33
|
+
@leveling_threshold = leveling_threshold
|
|
34
|
+
@denominators_class = denominators_class
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def project(simulation)
|
|
38
|
+
result = @proportional.project(simulation)
|
|
39
|
+
threshold = @leveling_threshold * simulation.values.inject(:+)
|
|
40
|
+
quotients = []
|
|
41
|
+
simulation.each_pair do |choice, votes|
|
|
42
|
+
next if votes < threshold
|
|
43
|
+
denominators(result[choice]).each do |d|
|
|
44
|
+
quotients << [choice, votes.to_f / d]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
seats = quotients.sort { |a, b| b.last <=> a.last }.map(&:first).slice(0, @leveling_seats)
|
|
48
|
+
seats.each do |seat|
|
|
49
|
+
if result.key?(seat)
|
|
50
|
+
result[seat] += 1
|
|
51
|
+
else
|
|
52
|
+
result[seat] = 1
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
result
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def denominators(seats)
|
|
61
|
+
@denominators_class.get(seats + @leveling_seats).reverse_each.take(@leveling_seats)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2020 Filip van Laenen <f.a.vanlaenen@ieee.org>
|
|
4
|
+
#
|
|
5
|
+
# This file is part of SAPoR.
|
|
6
|
+
#
|
|
7
|
+
# SAPoR is free software: you can redistribute it and/or modify it under the
|
|
8
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
9
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
10
|
+
# version.
|
|
11
|
+
#
|
|
12
|
+
# SAPoR is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
13
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
14
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You can find a copy of the GNU General Public License in /doc/gpl.txt
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Sapor
|
|
20
|
+
#
|
|
21
|
+
# Class representing a proportional electoral system with more than one
|
|
22
|
+
# district.
|
|
23
|
+
#
|
|
24
|
+
class MultiDistrictProportional
|
|
25
|
+
def initialize(last_election_result, last_detailed_election_result,
|
|
26
|
+
seat_distribution, denominators_class, threshold = 0,
|
|
27
|
+
national_threshold = 0)
|
|
28
|
+
@last_election_result = last_election_result
|
|
29
|
+
@last_detailed_election_result = last_detailed_election_result
|
|
30
|
+
@seat_distribution = seat_distribution
|
|
31
|
+
@denominators_class = denominators_class
|
|
32
|
+
@threshold = threshold
|
|
33
|
+
@national_threshold = national_threshold
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def project(simulation)
|
|
37
|
+
allowed_parties = []
|
|
38
|
+
unless @national_threshold.zero?
|
|
39
|
+
threshold = @national_threshold * simulation.values.inject(:+)
|
|
40
|
+
simulation.each_pair do |choice, votes|
|
|
41
|
+
allowed_parties << choice if votes >= threshold
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
multiplicators = calculate_multiplicators(simulation)
|
|
45
|
+
result = create_empty_result(simulation)
|
|
46
|
+
@last_detailed_election_result.each_pair do |name, local_last_result|
|
|
47
|
+
no_of_seats = @seat_distribution[name]
|
|
48
|
+
seats = local_seats(no_of_seats, local_last_result, multiplicators,
|
|
49
|
+
allowed_parties)
|
|
50
|
+
add_seats_to_result(result, seats)
|
|
51
|
+
end
|
|
52
|
+
result
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def add_seats_to_result(result, seats)
|
|
58
|
+
seats.each do |seat|
|
|
59
|
+
if result.key?(seat)
|
|
60
|
+
result[seat] += 1
|
|
61
|
+
else
|
|
62
|
+
result[seat] = 1
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def calculate_multiplicators(simulation)
|
|
68
|
+
simulation_sum = simulation.values.inject(:+)
|
|
69
|
+
last_election_sum = @last_election_result.values.inject(:+)
|
|
70
|
+
multiplicators = {}
|
|
71
|
+
simulation.each_key do |choice|
|
|
72
|
+
new_fraction = simulation[choice].to_f / simulation_sum
|
|
73
|
+
last_fraction = @last_election_result[choice].to_f / last_election_sum
|
|
74
|
+
multiplicators[choice] = new_fraction / last_fraction
|
|
75
|
+
end
|
|
76
|
+
multiplicators
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def create_empty_result(simulation)
|
|
80
|
+
result = {}
|
|
81
|
+
simulation.each_key do |choice|
|
|
82
|
+
result[choice] = 0
|
|
83
|
+
end
|
|
84
|
+
result[OTHER] = 0
|
|
85
|
+
result
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def local_votes(local_last_result, multiplicators)
|
|
89
|
+
local_votes = {}
|
|
90
|
+
local_last_result.each_pair do |choice, votes|
|
|
91
|
+
local_votes[choice] = if multiplicators.key?(choice)
|
|
92
|
+
votes * multiplicators[choice]
|
|
93
|
+
else
|
|
94
|
+
votes
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
local_votes
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def local_quotients(local_votes, local_threshold, no_of_seats,
|
|
101
|
+
allowed_parties)
|
|
102
|
+
local_quotients = []
|
|
103
|
+
local_votes.each_pair do |choice, new_value|
|
|
104
|
+
next unless allowed_parties.empty? || allowed_parties.include?(choice)
|
|
105
|
+
next if new_value < local_threshold
|
|
106
|
+
@denominators_class.get(no_of_seats).each do |d|
|
|
107
|
+
local_quotients << [choice, new_value.to_f / d]
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
local_quotients
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def local_seats(no_of_seats, local_last_result, multiplicators,
|
|
114
|
+
allowed_parties)
|
|
115
|
+
local_votes = local_votes(local_last_result, multiplicators)
|
|
116
|
+
local_threshold = local_votes.values.inject(:+).to_f * @threshold
|
|
117
|
+
local_quotients = local_quotients(local_votes, local_threshold,
|
|
118
|
+
no_of_seats, allowed_parties)
|
|
119
|
+
sorted_quotients = local_quotients.sort { |a, b| b.last <=> a.last }
|
|
120
|
+
sorted_quotients.map(&:first).slice(0, no_of_seats)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2020 Filip van Laenen <f.a.vanlaenen@ieee.org>
|
|
4
|
+
#
|
|
5
|
+
# This file is part of SAPoR.
|
|
6
|
+
#
|
|
7
|
+
# SAPoR is free software: you can redistribute it and/or modify it under the
|
|
8
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
9
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
10
|
+
# version.
|
|
11
|
+
#
|
|
12
|
+
# SAPoR is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
13
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
14
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You can find a copy of the GNU General Public License in /doc/gpl.txt
|
|
17
|
+
#
|
|
18
|
+
|
|
19
|
+
module Sapor
|
|
20
|
+
#
|
|
21
|
+
# Class representing a proportional electoral system with more than one
|
|
22
|
+
# district.
|
|
23
|
+
#
|
|
24
|
+
class MultiDistrictVariableThresholdProportional
|
|
25
|
+
def initialize(last_election_result, last_detailed_election_result,
|
|
26
|
+
seat_distribution, denominators_class,
|
|
27
|
+
party_list_threshold, coalition_list_threshold,
|
|
28
|
+
coalition_lists, minority_lists)
|
|
29
|
+
@last_election_result = last_election_result
|
|
30
|
+
@last_detailed_election_result = last_detailed_election_result
|
|
31
|
+
@seat_distribution = seat_distribution
|
|
32
|
+
@denominators_class = denominators_class
|
|
33
|
+
@party_list_threshold = party_list_threshold
|
|
34
|
+
@coalition_list_threshold = coalition_list_threshold
|
|
35
|
+
@coalition_lists = coalition_lists
|
|
36
|
+
@minority_lists = minority_lists
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def project(simulation)
|
|
40
|
+
allowed_parties = []
|
|
41
|
+
total_votes = simulation.values.inject(:+)
|
|
42
|
+
party_list_threshold = @party_list_threshold * total_votes
|
|
43
|
+
coalition_list_threshold = @coalition_list_threshold * total_votes
|
|
44
|
+
simulation.each_pair do |choice, votes|
|
|
45
|
+
next unless @minority_lists.include?(choice) ||
|
|
46
|
+
@coalition_lists.include?(choice) &&
|
|
47
|
+
votes >= coalition_list_threshold ||
|
|
48
|
+
!@coalition_lists.include?(choice) &&
|
|
49
|
+
votes >= party_list_threshold
|
|
50
|
+
allowed_parties << choice
|
|
51
|
+
end
|
|
52
|
+
multiplicators = calculate_multiplicators(simulation)
|
|
53
|
+
result = create_empty_result(simulation)
|
|
54
|
+
@last_detailed_election_result.each_pair do |name, local_last_result|
|
|
55
|
+
no_of_seats = @seat_distribution[name]
|
|
56
|
+
seats = local_seats(no_of_seats, local_last_result, multiplicators,
|
|
57
|
+
allowed_parties)
|
|
58
|
+
add_seats_to_result(result, seats)
|
|
59
|
+
end
|
|
60
|
+
result
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def add_seats_to_result(result, seats)
|
|
66
|
+
seats.each do |seat|
|
|
67
|
+
if result.key?(seat)
|
|
68
|
+
result[seat] += 1
|
|
69
|
+
else
|
|
70
|
+
result[seat] = 1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def calculate_multiplicators(simulation)
|
|
76
|
+
simulation_sum = simulation.values.inject(:+)
|
|
77
|
+
last_election_sum = @last_election_result.values.inject(:+)
|
|
78
|
+
multiplicators = {}
|
|
79
|
+
simulation.each_key do |choice|
|
|
80
|
+
new_fraction = simulation[choice].to_f / simulation_sum
|
|
81
|
+
last_fraction = @last_election_result[choice].to_f / last_election_sum
|
|
82
|
+
multiplicators[choice] = new_fraction / last_fraction
|
|
83
|
+
end
|
|
84
|
+
multiplicators
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def create_empty_result(simulation)
|
|
88
|
+
result = {}
|
|
89
|
+
simulation.each_key do |choice|
|
|
90
|
+
result[choice] = 0
|
|
91
|
+
end
|
|
92
|
+
result[OTHER] = 0
|
|
93
|
+
result
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def local_votes(local_last_result, multiplicators)
|
|
97
|
+
local_votes = {}
|
|
98
|
+
local_last_result.each_pair do |choice, votes|
|
|
99
|
+
local_votes[choice] = if multiplicators.key?(choice)
|
|
100
|
+
votes * multiplicators[choice]
|
|
101
|
+
else
|
|
102
|
+
votes
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
local_votes
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def local_quotients(local_votes, no_of_seats, allowed_parties)
|
|
109
|
+
local_quotients = []
|
|
110
|
+
local_votes.each_pair do |choice, new_value|
|
|
111
|
+
next unless allowed_parties.empty? || allowed_parties.include?(choice)
|
|
112
|
+
@denominators_class.get(no_of_seats).each do |d|
|
|
113
|
+
local_quotients << [choice, new_value.to_f / d]
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
local_quotients
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def local_seats(no_of_seats, local_last_result, multiplicators,
|
|
120
|
+
allowed_parties)
|
|
121
|
+
local_votes = local_votes(local_last_result, multiplicators)
|
|
122
|
+
local_quotients = local_quotients(local_votes, no_of_seats,
|
|
123
|
+
allowed_parties)
|
|
124
|
+
sorted_quotients = local_quotients.sort { |a, b| b.last <=> a.last }
|
|
125
|
+
sorted_quotients.map(&:first).slice(0, no_of_seats)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
4
|
+
# Copyright (C) 2020 Filip van Laenen <f.a.vanlaenen@ieee.org>
|
|
5
|
+
#
|
|
6
|
+
# This file is part of SAPoR.
|
|
7
|
+
#
|
|
8
|
+
# SAPoR is free software: you can redistribute it and/or modify it under the
|
|
9
|
+
# terms of the GNU General Public License as published by the Free Software
|
|
10
|
+
# Foundation, either version 3 of the License, or (at your option) any later
|
|
11
|
+
# version.
|
|
12
|
+
#
|
|
13
|
+
# SAPoR is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
14
|
+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
15
|
+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You can find a copy of the GNU General Public License in /doc/gpl.txt
|
|
18
|
+
#
|
|
19
|
+
|
|
20
|
+
module Sapor
|
|
21
|
+
#
|
|
22
|
+
# Module to format numbers.
|
|
23
|
+
#
|
|
24
|
+
module NumberFormatter
|
|
25
|
+
def three_digits_percentage(number)
|
|
26
|
+
if number >= 0.9995 || number < 0.000005
|
|
27
|
+
sprintf('%.0f', number * 100) + '%'
|
|
28
|
+
elsif number >= 0.09995
|
|
29
|
+
sprintf('%.1f', number * 100) + '%'
|
|
30
|
+
elsif number >= 0.009995
|
|
31
|
+
sprintf('%.2f', number * 100) + '%'
|
|
32
|
+
else
|
|
33
|
+
sprintf('%.3f', number * 100) + '%'
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def six_char_percentage(number)
|
|
38
|
+
sprintf('%5.1f', number * 100) + '%'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def with_thousands_separator(integer)
|
|
42
|
+
integer.to_s.reverse.gsub(/...(?=.)/, '\&,').reverse
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|