sapor 0.3.4
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/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 +150 -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/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 +286 -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 +82 -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-jxcat.rb +109 -0
- data/lib/sapor/regional_data/catalonia-no-jxsi.rb +96 -0
- data/lib/sapor/regional_data/catalonia.rb +96 -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 +81 -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_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 +81 -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_france_2019.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.psv +85 -0
- data/lib/sapor/regional_data/iceland.rb +133 -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.rb +112 -0
- data/lib/sapor/regional_data/latvia_kpv.rb +112 -0
- data/lib/sapor/regional_data/latvia_kpv_p_par.rb +112 -0
- data/lib/sapor/regional_data/latvia_kpv_par.rb +112 -0
- data/lib/sapor/regional_data/luxembourg-20131020.psv +76 -0
- data/lib/sapor/regional_data/luxembourg.rb +82 -0
- data/lib/sapor/regional_data/netherlands.rb +108 -0
- data/lib/sapor/regional_data/norway.rb +425 -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 +74 -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_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_2019_spec.rb +73 -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/largest_remainder_spec.rb +79 -0
- data/spec/unit/latvia_kpv_p_par_spec.rb +38 -0
- data/spec/unit/latvia_kpv_par_spec.rb +38 -0
- data/spec/unit/latvia_kpv_spec.rb +38 -0
- data/spec/unit/latvia_spec.rb +60 -0
- data/spec/unit/luxembourg_spec.rb +54 -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 +64 -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 +490 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
20
|
+
|
|
21
|
+
describe Sapor::Denmark, '#area_code' do
|
|
22
|
+
it 'returns DK as the area code' do
|
|
23
|
+
expect(Sapor::Denmark.instance.area_code).to eq('DK')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe Sapor::Denmark, '#no_of_seats' do
|
|
28
|
+
it 'returns 179 as the number of seats' do
|
|
29
|
+
expect(Sapor::Denmark.instance.no_of_seats).to eq(175)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Sapor::Denmark, '#population_size' do
|
|
34
|
+
it 'returns a population size of 3,518,987' do
|
|
35
|
+
expect(Sapor::Denmark.instance.population_size).to eq(3_518_987)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe Sapor::Denmark, '#seats' do
|
|
40
|
+
it 'calculates the number of seats for the election of 2015 correctly' do
|
|
41
|
+
Denmark = Sapor::Denmark.instance
|
|
42
|
+
results = Denmark.overall_election_results_of_2015
|
|
43
|
+
seats = Denmark.seats(results)
|
|
44
|
+
expect(seats['Socialdemokraterne']).to eq(47 - 2)
|
|
45
|
+
expect(seats['Dansk Folkeparti']).to eq(37 - 1)
|
|
46
|
+
expect(seats['Venstre']).to eq(34 - 1)
|
|
47
|
+
expect(seats['Enhedslisten–De Rød-Grønne']).to eq(14 - 1)
|
|
48
|
+
expect(seats['Liberal Alliance']).to eq(13)
|
|
49
|
+
expect(seats['Alternativet']).to eq(9 - 1)
|
|
50
|
+
expect(seats['Radikale Venstre']).to eq(8)
|
|
51
|
+
expect(seats['Socialistisk Folkeparti']).to eq(7)
|
|
52
|
+
expect(seats['Det Konservative Folkeparti']).to eq(6)
|
|
53
|
+
expect(seats['Nye Borgerlige']).to eq(6)
|
|
54
|
+
expect(seats['Kristendemokraterne']).to eq(0)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
20
|
+
|
|
21
|
+
describe Sapor::DenmarkWithEAndP, '#area_code' do
|
|
22
|
+
it 'returns DK∪{E,P} as the area code' do
|
|
23
|
+
expect(Sapor::DenmarkWithEAndP.instance.area_code).to eq('DK∪{E,P}')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe Sapor::DenmarkWithEAndP, '#no_of_seats' do
|
|
28
|
+
it 'returns 179 as the number of seats' do
|
|
29
|
+
expect(Sapor::DenmarkWithEAndP.instance.no_of_seats).to eq(175)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Sapor::DenmarkWithEAndP, '#population_size' do
|
|
34
|
+
it 'returns a population size of 3,518,987' do
|
|
35
|
+
expect(Sapor::DenmarkWithEAndP.instance.population_size).to eq(3_518_987)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe Sapor::DenmarkWithEAndP, '#seats' do
|
|
40
|
+
it 'calculates the number of seats for the election of 2015 correctly' do
|
|
41
|
+
Denmark = Sapor::DenmarkWithEAndP.instance
|
|
42
|
+
results = Denmark.overall_election_results_of_2015
|
|
43
|
+
seats = Denmark.seats(results)
|
|
44
|
+
expect(seats['Socialdemokraterne']).to eq(37)
|
|
45
|
+
expect(seats['Dansk Folkeparti']).to eq(29)
|
|
46
|
+
expect(seats['Venstre']).to eq(27)
|
|
47
|
+
expect(seats['Klaus Riskær Pedersen']).to eq(27)
|
|
48
|
+
expect(seats['Enhedslisten–De Rød-Grønne']).to eq(11)
|
|
49
|
+
expect(seats['Liberal Alliance']).to eq(10)
|
|
50
|
+
expect(seats['Alternativet']).to eq(7)
|
|
51
|
+
expect(seats['Radikale Venstre']).to eq(6)
|
|
52
|
+
expect(seats['Socialistisk Folkeparti']).to eq(6)
|
|
53
|
+
expect(seats['Det Konservative Folkeparti']).to eq(5)
|
|
54
|
+
expect(seats['Nye Borgerlige']).to eq(5)
|
|
55
|
+
expect(seats['Stram Kurs']).to eq(5)
|
|
56
|
+
expect(seats['Kristendemokraterne']).to eq(0)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
20
|
+
|
|
21
|
+
describe Sapor::DenmarkWithE, '#area_code' do
|
|
22
|
+
it 'returns DK∪{E} as the area code' do
|
|
23
|
+
expect(Sapor::DenmarkWithE.instance.area_code).to eq('DK∪{E}')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe Sapor::DenmarkWithE, '#no_of_seats' do
|
|
28
|
+
it 'returns 179 as the number of seats' do
|
|
29
|
+
expect(Sapor::DenmarkWithE.instance.no_of_seats).to eq(175)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Sapor::DenmarkWithE, '#population_size' do
|
|
34
|
+
it 'returns a population size of 3,518,987' do
|
|
35
|
+
expect(Sapor::DenmarkWithE.instance.population_size).to eq(3_518_987)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe Sapor::DenmarkWithE, '#seats' do
|
|
40
|
+
it 'calculates the number of seats for the election of 2015 correctly' do
|
|
41
|
+
Denmark = Sapor::DenmarkWithE.instance
|
|
42
|
+
results = Denmark.overall_election_results_of_2015
|
|
43
|
+
seats = Denmark.seats(results)
|
|
44
|
+
expect(seats['Socialdemokraterne']).to eq(38)
|
|
45
|
+
expect(seats['Dansk Folkeparti']).to eq(30)
|
|
46
|
+
expect(seats['Venstre']).to eq(28)
|
|
47
|
+
expect(seats['Klaus Riskær Pedersen']).to eq(28)
|
|
48
|
+
expect(seats['Enhedslisten–De Rød-Grønne']).to eq(11)
|
|
49
|
+
expect(seats['Liberal Alliance']).to eq(11)
|
|
50
|
+
expect(seats['Alternativet']).to eq(7)
|
|
51
|
+
expect(seats['Radikale Venstre']).to eq(6)
|
|
52
|
+
expect(seats['Socialistisk Folkeparti']).to eq(6)
|
|
53
|
+
expect(seats['Det Konservative Folkeparti']).to eq(5)
|
|
54
|
+
expect(seats['Nye Borgerlige']).to eq(5)
|
|
55
|
+
expect(seats['Kristendemokraterne']).to eq(0)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
20
|
+
|
|
21
|
+
describe Sapor::DenmarkWithP, '#area_code' do
|
|
22
|
+
it 'returns DK∪{P} as the area code' do
|
|
23
|
+
expect(Sapor::DenmarkWithP.instance.area_code).to eq('DK∪{P}')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe Sapor::DenmarkWithP, '#no_of_seats' do
|
|
28
|
+
it 'returns 179 as the number of seats' do
|
|
29
|
+
expect(Sapor::DenmarkWithP.instance.no_of_seats).to eq(175)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Sapor::DenmarkWithP, '#population_size' do
|
|
34
|
+
it 'returns a population size of 3,518,987' do
|
|
35
|
+
expect(Sapor::DenmarkWithP.instance.population_size).to eq(3_518_987)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe Sapor::DenmarkWithP, '#seats' do
|
|
40
|
+
it 'calculates the number of seats for the election of 2015 correctly' do
|
|
41
|
+
Denmark = Sapor::DenmarkWithP.instance
|
|
42
|
+
results = Denmark.overall_election_results_of_2015
|
|
43
|
+
seats = Denmark.seats(results)
|
|
44
|
+
expect(seats['Socialdemokraterne']).to eq(43)
|
|
45
|
+
expect(seats['Dansk Folkeparti']).to eq(35)
|
|
46
|
+
expect(seats['Venstre']).to eq(32)
|
|
47
|
+
expect(seats['Enhedslisten–De Rød-Grønne']).to eq(13)
|
|
48
|
+
expect(seats['Liberal Alliance']).to eq(12)
|
|
49
|
+
expect(seats['Alternativet']).to eq(8)
|
|
50
|
+
expect(seats['Radikale Venstre']).to eq(8)
|
|
51
|
+
expect(seats['Socialistisk Folkeparti']).to eq(7)
|
|
52
|
+
expect(seats['Det Konservative Folkeparti']).to eq(6)
|
|
53
|
+
expect(seats['Nye Borgerlige']).to eq(6)
|
|
54
|
+
expect(seats['Stram Kurs']).to eq(5)
|
|
55
|
+
expect(seats['Kristendemokraterne']).to eq(0)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
3
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
20
|
+
|
|
21
|
+
describe Sapor::DhondtDenominators, '#get' do
|
|
22
|
+
it 'returns [1, 2, 3, 4, 5] as the five first elements' do
|
|
23
|
+
denominators = Sapor::DhondtDenominators.get(5).each.to_a
|
|
24
|
+
expect(denominators).to eq([1, 2, 3, 4, 5])
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe Sapor::SainteLague12Denominators, '#get' do
|
|
29
|
+
it 'returns [1.2, 3, 5, 7, 9] as the five first elements' do
|
|
30
|
+
denominators = Sapor::SainteLague12Denominators.get(5).each.to_a
|
|
31
|
+
expect(denominators).to eq([1.2, 3, 5, 7, 9])
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe Sapor::SainteLague14Denominators, '#get' do
|
|
36
|
+
it 'returns [1.4, 3, 5, 7, 9] as the five first elements' do
|
|
37
|
+
denominators = Sapor::SainteLague14Denominators.get(5).each.to_a
|
|
38
|
+
expect(denominators).to eq([1.4, 3, 5, 7, 9])
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
4
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
21
|
+
|
|
22
|
+
SAMPLE_RESULTS = { 'Red' => 1, 'Green' => 2, 'Blue' => 3, 'Other' => 1 }
|
|
23
|
+
SAMPLE_POPULATION_SIZE = 1_000_000
|
|
24
|
+
|
|
25
|
+
describe Sapor::Dichotomies, '#confidence_interval_values' do
|
|
26
|
+
it 'returns the confidence interval values' do
|
|
27
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
28
|
+
SAMPLE_POPULATION_SIZE)
|
|
29
|
+
expect(dichotomies.confidence_interval_values('Red', 0.95)).to \
|
|
30
|
+
eq([500_000])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'returns the non-default confidence interval values' do
|
|
34
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
35
|
+
SAMPLE_POPULATION_SIZE)
|
|
36
|
+
dichotomies.refine
|
|
37
|
+
expect(dichotomies.confidence_interval_values('Red', 0.9999).sort).to \
|
|
38
|
+
eq([166_667, 500_000, 833_333])
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe Sapor::Dichotomies, '#error_estimate' do
|
|
43
|
+
it 'returns the largest error estimate of the underlying Dichotomy ' \
|
|
44
|
+
'objects' do
|
|
45
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
46
|
+
SAMPLE_POPULATION_SIZE)
|
|
47
|
+
expect(dichotomies.error_estimate).to eq(1)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe Sapor::Dichotomies, '#progress_report' do
|
|
52
|
+
it 'reports progress as 1 data point by default' do
|
|
53
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
54
|
+
SAMPLE_POPULATION_SIZE)
|
|
55
|
+
expect(dichotomies.progress_report).to eq('Number of data points: 1.')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'reports progress as 3 data points after the first refinement' do
|
|
59
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
60
|
+
SAMPLE_POPULATION_SIZE)
|
|
61
|
+
dichotomies.refine
|
|
62
|
+
expect(dichotomies.progress_report).to eq('Number of data points: 3.')
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe Sapor::Dichotomies, '#report' do
|
|
67
|
+
it 'produces a report by default for short choice labels' do
|
|
68
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
69
|
+
SAMPLE_POPULATION_SIZE)
|
|
70
|
+
expected_report = 'Most probable fractions and 95% confidence ' \
|
|
71
|
+
"intervals:\n" \
|
|
72
|
+
"Choice MPF CI(95%)\n" \
|
|
73
|
+
"Blue 50.0% 0.0%–100.0%\n" \
|
|
74
|
+
"Green 50.0% 0.0%–100.0%\n" \
|
|
75
|
+
"Red 50.0% 0.0%–100.0%\n" \
|
|
76
|
+
'Other 50.0% 0.0%–100.0%'
|
|
77
|
+
expect(dichotomies.report).to eq(expected_report)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'produces a report by default for long choice labels' do
|
|
81
|
+
dichotomies = Sapor::Dichotomies.new({ 'Dark Red' => 1,
|
|
82
|
+
'Light Green' => 2,
|
|
83
|
+
'Medium Blue' => 3, 'Other' => 1 },
|
|
84
|
+
SAMPLE_POPULATION_SIZE)
|
|
85
|
+
expected_report = 'Most probable fractions and 95% confidence ' \
|
|
86
|
+
"intervals:\n" \
|
|
87
|
+
"Choice MPF CI(95%)\n" \
|
|
88
|
+
"Dark Red 50.0% 0.0%–100.0%\n" \
|
|
89
|
+
"Light Green 50.0% 0.0%–100.0%\n" \
|
|
90
|
+
"Medium Blue 50.0% 0.0%–100.0%\n" \
|
|
91
|
+
'Other 50.0% 0.0%–100.0%'
|
|
92
|
+
expect(dichotomies.report).to eq(expected_report)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'produces a report after the first refinement' do
|
|
96
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
97
|
+
SAMPLE_POPULATION_SIZE)
|
|
98
|
+
dichotomies.refine
|
|
99
|
+
expected_report = 'Most probable fractions and 95% confidence ' \
|
|
100
|
+
"intervals:\n" \
|
|
101
|
+
"Choice MPF CI(95%)\n" \
|
|
102
|
+
"Blue 50.0% 0.0%–100.0%\n" \
|
|
103
|
+
"Green 16.7% 0.0%– 66.7%\n" \
|
|
104
|
+
"Red 16.7% 0.0%– 66.7%\n" \
|
|
105
|
+
'Other 16.7% 0.0%– 66.7%'
|
|
106
|
+
expect(dichotomies.report).to eq(expected_report)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'sorts the choices according to MPV' do
|
|
110
|
+
dichotomies = Sapor::Dichotomies.new({ 'Red' => 3, 'Green' => 2,
|
|
111
|
+
'Blue' => 1, 'Other' => 1 },
|
|
112
|
+
SAMPLE_POPULATION_SIZE)
|
|
113
|
+
dichotomies.refine
|
|
114
|
+
expected_report = 'Most probable fractions and 95% confidence ' \
|
|
115
|
+
"intervals:\n" \
|
|
116
|
+
"Choice MPF CI(95%)\n" \
|
|
117
|
+
"Red 50.0% 0.0%–100.0%\n" \
|
|
118
|
+
"Blue 16.7% 0.0%– 66.7%\n" \
|
|
119
|
+
"Green 16.7% 0.0%– 66.7%\n" \
|
|
120
|
+
'Other 16.7% 0.0%– 66.7%'
|
|
121
|
+
expect(dichotomies.report).to eq(expected_report)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "puts Other on the last line, even if it's listed first and largest" do
|
|
125
|
+
dichotomies = Sapor::Dichotomies.new({ 'Other' => 4, 'Red' => 1,
|
|
126
|
+
'Green' => 2, 'Blue' => 3 },
|
|
127
|
+
SAMPLE_POPULATION_SIZE)
|
|
128
|
+
dichotomies.refine
|
|
129
|
+
expected_report = 'Most probable fractions and 95% confidence ' \
|
|
130
|
+
"intervals:\n" \
|
|
131
|
+
"Choice MPF CI(95%)\n" \
|
|
132
|
+
"Blue 16.7% 0.0%– 66.7%\n" \
|
|
133
|
+
"Green 16.7% 0.0%– 66.7%\n" \
|
|
134
|
+
"Red 16.7% 0.0%– 66.7%\n" \
|
|
135
|
+
'Other 50.0% 0.0%– 66.7%'
|
|
136
|
+
expect(dichotomies.report).to eq(expected_report)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
it 'includes threshold probabilities when a threshold provided' do
|
|
140
|
+
dichotomies = Sapor::Dichotomies.new(SAMPLE_RESULTS,
|
|
141
|
+
SAMPLE_POPULATION_SIZE,
|
|
142
|
+
0.15)
|
|
143
|
+
dichotomies.refine
|
|
144
|
+
dichotomies.refine
|
|
145
|
+
expected_report = 'Most probable fractions and 95% confidence ' \
|
|
146
|
+
"intervals:\n" \
|
|
147
|
+
"Choice MPF CI(95%) P(≥15%)\n" \
|
|
148
|
+
"Blue 38.9% 11.1%– 77.8% 99.6%\n" \
|
|
149
|
+
"Green 27.8% 0.0%– 66.7% 95.7%\n" \
|
|
150
|
+
"Red 16.7% 0.0%– 55.6% 76.1%\n" \
|
|
151
|
+
'Other 16.7% 0.0%– 55.6% 76.1%'
|
|
152
|
+
expect(dichotomies.report).to eq(expected_report)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
#
|
|
3
|
+
# Statistical Analysis of Polling Results (SAPoR)
|
|
4
|
+
# Copyright (C) 2016 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
|
+
require 'spec_helper'
|
|
21
|
+
|
|
22
|
+
def dichotomy_of_eight
|
|
23
|
+
Sapor::Dichotomy.new(2, 5, 8)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def dichotomy_of_nine
|
|
27
|
+
Sapor::Dichotomy.new(2, 5, 9)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def dichotomy_of_thousand
|
|
31
|
+
Sapor::Dichotomy.new(2, 5, 1000)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def dichotomy_of_nine_hundred_ninety_nine
|
|
35
|
+
Sapor::Dichotomy.new(2, 5, 999)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
describe Sapor::Dichotomy, '#new' do
|
|
39
|
+
it 'creates an array with a value at 50% of the population size' do
|
|
40
|
+
expect(dichotomy_of_eight.values).to eq([4])
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'creates an array with a value at 50% of the population size' \
|
|
44
|
+
' (rounding)' do
|
|
45
|
+
expect(dichotomy_of_nine.values).to eq([4])
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'creates an array with a combination for 50% of the population size' do
|
|
49
|
+
expect(dichotomy_of_eight.combinations(4)).to eq(24.to_lf)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe Sapor::Dichotomy, '#confidence_interval' do
|
|
54
|
+
it 'returns [0%, 100%] after new for default level 95%' do
|
|
55
|
+
expect(dichotomy_of_eight.confidence_interval).to eq([0.0, 1.0])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'returns the default 95% confidence interval after one refinement' do
|
|
59
|
+
dichotomy = Sapor::Dichotomy.new(20, 50, 80)
|
|
60
|
+
dichotomy.refine
|
|
61
|
+
expect(dichotomy.confidence_interval).to eq([0.3375, 0.6625])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it 'returns the default 95% confidence interval after three refinements' do
|
|
65
|
+
dichotomy = dichotomy_of_thousand
|
|
66
|
+
dichotomy.refine
|
|
67
|
+
dichotomy.refine
|
|
68
|
+
dichotomy.refine
|
|
69
|
+
expect(dichotomy.confidence_interval).to eq([0.112, 0.777])
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'returns the 80% confidence interval after three refinements' do
|
|
73
|
+
dichotomy = dichotomy_of_thousand
|
|
74
|
+
dichotomy.refine
|
|
75
|
+
dichotomy.refine
|
|
76
|
+
dichotomy.refine
|
|
77
|
+
expect(dichotomy.confidence_interval(0.8)).to eq([0.186, 0.666])
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe Sapor::Dichotomy, '#error_estimate' do
|
|
82
|
+
it 'is 0 when population size is reached' do
|
|
83
|
+
dichotomy = dichotomy_of_eight
|
|
84
|
+
dichotomy.refine
|
|
85
|
+
dichotomy.refine
|
|
86
|
+
dichotomy.refine
|
|
87
|
+
expect(dichotomy.error_estimate).to eq(0)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'is at least the resolution (no refinement)' do
|
|
91
|
+
dichotomy = dichotomy_of_eight
|
|
92
|
+
expect(dichotomy.error_estimate).to eq(1.0)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'is at least the resolution (one refinement)' do
|
|
96
|
+
dichotomy = dichotomy_of_eight
|
|
97
|
+
dichotomy.refine
|
|
98
|
+
expect(dichotomy.error_estimate).to eq(1.to_f / 3)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe Sapor::Dichotomy, '#most_probable_fraction' do
|
|
103
|
+
it 'returns the fraction of the single value after new' do
|
|
104
|
+
expect(dichotomy_of_eight.most_probable_fraction).to eq(0.5)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'returns the one probable value after one refinement' do
|
|
108
|
+
dichotomy = dichotomy_of_eight
|
|
109
|
+
dichotomy.refine
|
|
110
|
+
expect(dichotomy.most_probable_fraction).to eq(0.5)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'returns the new most probable value after two refinements' do
|
|
114
|
+
dichotomy = dichotomy_of_eight
|
|
115
|
+
dichotomy.refine
|
|
116
|
+
dichotomy.refine
|
|
117
|
+
expect(dichotomy.most_probable_fraction).to eq(0.375)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe Sapor::Dichotomy, '#most_probable_value' do
|
|
122
|
+
it 'returns the single value after new' do
|
|
123
|
+
expect(dichotomy_of_eight.most_probable_value).to eq(4)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'returns the one probable value after one refinement' do
|
|
127
|
+
dichotomy = dichotomy_of_eight
|
|
128
|
+
dichotomy.refine
|
|
129
|
+
expect(dichotomy.most_probable_value).to eq(4)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it 'returns the new most probable value after two refinements' do
|
|
133
|
+
dichotomy = dichotomy_of_eight
|
|
134
|
+
dichotomy.refine
|
|
135
|
+
dichotomy.refine
|
|
136
|
+
expect(dichotomy.most_probable_value).to eq(3)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
describe Sapor::Dichotomy, '#refine' do
|
|
141
|
+
it 'adds values after one refinement (power of three)' do
|
|
142
|
+
dichotomy = dichotomy_of_eight
|
|
143
|
+
dichotomy.refine
|
|
144
|
+
expect(dichotomy.values.sort).to eq([1, 4, 7])
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'adds values after one refinement (small population)' do
|
|
148
|
+
dichotomy = dichotomy_of_nine
|
|
149
|
+
dichotomy.refine
|
|
150
|
+
expect(dichotomy.values.sort).to eq([1, 4, 7])
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it 'adds values after one refinement (large population)' do
|
|
154
|
+
dichotomy = dichotomy_of_thousand
|
|
155
|
+
dichotomy.refine
|
|
156
|
+
expect(dichotomy.values.sort).to eq([167, 500, 833])
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'adds values after two refinements (power of three)' do
|
|
160
|
+
dichotomy = dichotomy_of_eight
|
|
161
|
+
dichotomy.refine
|
|
162
|
+
dichotomy.refine
|
|
163
|
+
expect(dichotomy.values.sort).to eq([0, 1, 2, 3, 4, 5, 6, 7, 8])
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'adds values after two refinements (small population)' do
|
|
167
|
+
dichotomy = dichotomy_of_nine
|
|
168
|
+
dichotomy.refine
|
|
169
|
+
dichotomy.refine
|
|
170
|
+
expect(dichotomy.values.sort).to eq([0, 1, 2, 3, 4, 5, 6, 7, 8])
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
it 'adds values after two refinements (small population)' do
|
|
174
|
+
dichotomy = Sapor::Dichotomy.new(2, 5, 60)
|
|
175
|
+
dichotomy.refine
|
|
176
|
+
dichotomy.refine
|
|
177
|
+
expect(dichotomy.values.sort).to eq([3, 10, 17, 23, 30, 37, 43, 50, 57])
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'adds values after two refinements (large population)' do
|
|
181
|
+
dichotomy = dichotomy_of_thousand
|
|
182
|
+
dichotomy.refine
|
|
183
|
+
dichotomy.refine
|
|
184
|
+
expect(dichotomy.values.sort).to eq([56, 167, 278, 389, 500, 611, 722, 833,
|
|
185
|
+
944])
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "doesn't add values when population size is reached" do
|
|
189
|
+
dichotomy = dichotomy_of_eight
|
|
190
|
+
dichotomy.refine
|
|
191
|
+
dichotomy.refine
|
|
192
|
+
dichotomy.refine
|
|
193
|
+
expect(dichotomy.values.sort).to eq([0, 1, 2, 3, 4, 5, 6, 7, 8])
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'fills up the values when population size is reached' do
|
|
197
|
+
dichotomy = dichotomy_of_nine
|
|
198
|
+
dichotomy.refine
|
|
199
|
+
dichotomy.refine
|
|
200
|
+
dichotomy.refine
|
|
201
|
+
expect(dichotomy.values.sort).to eq([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'fills up the values when population size is reached' do
|
|
205
|
+
dichotomy = Sapor::Dichotomy.new(2, 5, 11)
|
|
206
|
+
dichotomy.refine
|
|
207
|
+
dichotomy.refine
|
|
208
|
+
dichotomy.refine
|
|
209
|
+
expect(dichotomy.values.sort).to eq([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it 'adds combinations after a refinement' do
|
|
213
|
+
dichotomy = dichotomy_of_thousand
|
|
214
|
+
dichotomy.refine
|
|
215
|
+
expect(dichotomy.combinations(167)).to eq(1_330_493_216_416.to_lf)
|
|
216
|
+
expect(dichotomy.combinations(833)).to eq(264_177_353_440.to_lf)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'adds combinations of zero for impossible values' do
|
|
220
|
+
dichotomy = dichotomy_of_eight
|
|
221
|
+
dichotomy.refine
|
|
222
|
+
expect(dichotomy.combinations(1)).to eq(0.to_lf)
|
|
223
|
+
expect(dichotomy.combinations(7)).to eq(0.to_lf)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
describe Sapor::Dichotomy, '#threshold_probability' do
|
|
228
|
+
it 'returns 100% after new for a 50% threshold' do
|
|
229
|
+
expect(dichotomy_of_thousand.threshold_probability(0.5)).to eq(1)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it 'returns 0% after new for a 51% threshold' do
|
|
233
|
+
expect(dichotomy_of_thousand.threshold_probability(0.51)).to eq(0)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
it 'returns 100% for a 5% threshold after one refinement' do
|
|
237
|
+
dichotomy = dichotomy_of_thousand
|
|
238
|
+
dichotomy.refine
|
|
239
|
+
expect(dichotomy.threshold_probability(0.05)).to eq(1)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it 'returns 68% (after rounding) for a 50% threshold after one refinement' do
|
|
243
|
+
dichotomy = dichotomy_of_thousand
|
|
244
|
+
dichotomy.refine
|
|
245
|
+
expect(dichotomy.threshold_probability(0.5).round(2)).to eq(0.68)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
it 'returns 0% for a 95% threshold after one refinement' do
|
|
249
|
+
dichotomy = dichotomy_of_thousand
|
|
250
|
+
dichotomy.refine
|
|
251
|
+
expect(dichotomy.threshold_probability(0.95)).to eq(0)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
describe Sapor::Dichotomy, '#value_confidence_interval' do
|
|
256
|
+
it 'returns [0, population_size] values after new for default level 95%' do
|
|
257
|
+
expect(dichotomy_of_eight.value_confidence_interval).to eq([0, 8])
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'returns [0, population_size] values after new for level 80%' do
|
|
261
|
+
expect(dichotomy_of_eight.value_confidence_interval(0.8)).to eq([0, 8])
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it 'returns the value confidence interval after one refinement' do
|
|
265
|
+
dichotomy = Sapor::Dichotomy.new(20, 50, 80)
|
|
266
|
+
dichotomy.refine
|
|
267
|
+
expect(dichotomy.value_confidence_interval).to eq([27, 53])
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it 'returns the value confidence interval after full refinement' do
|
|
271
|
+
dichotomy = dichotomy_of_eight
|
|
272
|
+
dichotomy.refine
|
|
273
|
+
dichotomy.refine
|
|
274
|
+
expect(dichotomy.value_confidence_interval).to eq([2, 5])
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it 'returns the 80% value confidence interval after full refinement' do
|
|
278
|
+
dichotomy = dichotomy_of_eight
|
|
279
|
+
dichotomy.refine
|
|
280
|
+
dichotomy.refine
|
|
281
|
+
expect(dichotomy.value_confidence_interval(0.8)).to eq([2, 5])
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
it 'returns the value confidence interval after two refinements' do
|
|
285
|
+
dichotomy = dichotomy_of_thousand
|
|
286
|
+
dichotomy.refine
|
|
287
|
+
dichotomy.refine
|
|
288
|
+
expect(dichotomy.value_confidence_interval).to eq([112, 777])
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it 'returns the 80% value confidence interval after two refinements' do
|
|
292
|
+
dichotomy = dichotomy_of_thousand
|
|
293
|
+
dichotomy.refine
|
|
294
|
+
dichotomy.refine
|
|
295
|
+
expect(dichotomy.value_confidence_interval(0.8)).to eq([112, 666])
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
it 'returns the value confidence interval after three refinements' do
|
|
299
|
+
dichotomy = dichotomy_of_thousand
|
|
300
|
+
dichotomy.refine
|
|
301
|
+
dichotomy.refine
|
|
302
|
+
dichotomy.refine
|
|
303
|
+
expect(dichotomy.value_confidence_interval).to eq([112, 777])
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
it 'can return a confidence interval starting at 0 after refinements' do
|
|
307
|
+
dichotomy = Sapor::Dichotomy.new(0, 5, 1000)
|
|
308
|
+
dichotomy.refine
|
|
309
|
+
dichotomy.refine
|
|
310
|
+
expect(dichotomy.value_confidence_interval).to eq([0, 555])
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
it 'can return a confidence interval ending at population size after ' \
|
|
314
|
+
'refinements' do
|
|
315
|
+
dichotomy = Sapor::Dichotomy.new(5, 5, 1000)
|
|
316
|
+
dichotomy.refine
|
|
317
|
+
dichotomy.refine
|
|
318
|
+
expect(dichotomy.value_confidence_interval).to eq([445, 1000])
|
|
319
|
+
end
|
|
320
|
+
end
|