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.
Files changed (343) hide show
  1. checksums.yaml +7 -0
  2. data/Area Class Diagram.dia +0 -0
  3. data/Area Class Diagram.png +0 -0
  4. data/Class Diagram.dia +0 -0
  5. data/Class Diagram.png +0 -0
  6. data/Example-Catalonia.md +361 -0
  7. data/Example-Flanders.md +486 -0
  8. data/Example-Greece.md +25 -0
  9. data/Example-Oslo.md +678 -0
  10. data/Example-UnitedKingdom-Referendum.md +132 -0
  11. data/Examples.md +15 -0
  12. data/LICENSE +674 -0
  13. data/README.md +103 -0
  14. data/Rakefile +18 -0
  15. data/Technical Documentation.md +14 -0
  16. data/bin/create_installation_package.sh +49 -0
  17. data/bin/install.sh +45 -0
  18. data/bin/sapor.rb +24 -0
  19. data/bin/sapor.sh +106 -0
  20. data/data/hu/hungary-2014.txt +1680 -0
  21. data/data/hu/hungary_2014_screen_scraper.rb +48 -0
  22. data/data/hu/hungary_2014_to_psv.rb +80 -0
  23. data/data/hu/index-2014.txt +106 -0
  24. data/data/ie/2016-04-28_general-election-2016-candidate-details-csv_en.csv +552 -0
  25. data/data/ie/ireland_2016_to_psv.rb +138 -0
  26. data/data/no/2020-01-01_partifordeling_1_st_2017.csv +335 -0
  27. data/data/no/norway_2017_to_psv.rb +61 -0
  28. data/data/pl/2015-gl-lis-okr.csv +42 -0
  29. data/data/pl/poland_2015_to_psv.rb +79 -0
  30. data/data/pl/poland_2015_to_psv_with_ko_and_rsw.rb +94 -0
  31. data/data/pl/poland_2015_to_psv_with_ko_konf_kp_l_and_zp.rb +100 -0
  32. data/data/pl/poland_2015_to_psv_with_ko_sld_and_wi.rb +92 -0
  33. data/data/pl/poland_2015_to_psv_with_sld.rb +84 -0
  34. data/data/pl/poland_2015_to_psv_with_sld_and_wi.rb +85 -0
  35. data/data/uk/inject_ukip_2015_as_brexit_2019_in_2017.rb +54 -0
  36. data/data/uk/united_kingdom_2015.txt +651 -0
  37. data/data/uk/united_kingdom_2015_to_psv.rb +104 -0
  38. data/data/uk/united_kingdom_2017.txt +651 -0
  39. data/data/uk/united_kingdom_2017_to_psv.rb +104 -0
  40. data/data/uk/united_kingdom_2017_to_psv_with_brexit_and_chuk.rb +113 -0
  41. data/data/uk/united_kingdom_2017_to_psv_with_tig.rb +111 -0
  42. data/lib/sapor.rb +147 -0
  43. data/lib/sapor/binomials_cache.rb +45 -0
  44. data/lib/sapor/combinations_distribution.rb +222 -0
  45. data/lib/sapor/denominators.rb +67 -0
  46. data/lib/sapor/dichotomies.rb +138 -0
  47. data/lib/sapor/dichotomy.rb +164 -0
  48. data/lib/sapor/first_past_the_post.rb +82 -0
  49. data/lib/sapor/largest_remainder.rb +118 -0
  50. data/lib/sapor/log4r_logger.rb +49 -0
  51. data/lib/sapor/log_facade.rb +40 -0
  52. data/lib/sapor/many_past_the_post.rb +113 -0
  53. data/lib/sapor/multi_district_leveled_proportional.rb +64 -0
  54. data/lib/sapor/multi_district_proportional.rb +123 -0
  55. data/lib/sapor/multi_district_variable_threshold_proportional.rb +128 -0
  56. data/lib/sapor/number_formatter.rb +45 -0
  57. data/lib/sapor/options.rb +73 -0
  58. data/lib/sapor/poll.rb +282 -0
  59. data/lib/sapor/polychotomy.rb +200 -0
  60. data/lib/sapor/pseudorandom_multirange_enumerator.rb +87 -0
  61. data/lib/sapor/referendum_polychotomy.rb +165 -0
  62. data/lib/sapor/regional_data/area.rb +100 -0
  63. data/lib/sapor/regional_data/austria.rb +84 -0
  64. data/lib/sapor/regional_data/belgium-brussels-2014.psv +46 -0
  65. data/lib/sapor/regional_data/belgium-brussels-20190526.psv +33 -0
  66. data/lib/sapor/regional_data/belgium-flanders-2014.psv +80 -0
  67. data/lib/sapor/regional_data/belgium-flanders-20190526.psv +74 -0
  68. data/lib/sapor/regional_data/belgium-wallonia-2014.psv +114 -0
  69. data/lib/sapor/regional_data/belgium-wallonia-20190526.psv +93 -0
  70. data/lib/sapor/regional_data/belgium.rb +97 -0
  71. data/lib/sapor/regional_data/belgium_brussels.rb +62 -0
  72. data/lib/sapor/regional_data/belgium_flanders.rb +64 -0
  73. data/lib/sapor/regional_data/belgium_wallonia.rb +63 -0
  74. data/lib/sapor/regional_data/catalonia-2012-2015.psv +100 -0
  75. data/lib/sapor/regional_data/catalonia-2012.psv +87 -0
  76. data/lib/sapor/regional_data/catalonia-2015-jxcat.psv +68 -0
  77. data/lib/sapor/regional_data/catalonia-2015-no-jxsi.psv +68 -0
  78. data/lib/sapor/regional_data/catalonia-2015.psv +63 -0
  79. data/lib/sapor/regional_data/catalonia-20171221-with-vox.psv +67 -0
  80. data/lib/sapor/regional_data/catalonia-20171221.psv +61 -0
  81. data/lib/sapor/regional_data/catalonia.rb +124 -0
  82. data/lib/sapor/regional_data/denmark-20150618-with-e-and-p.psv +164 -0
  83. data/lib/sapor/regional_data/denmark-20150618-with-e.psv +153 -0
  84. data/lib/sapor/regional_data/denmark-20150618-with-p.psv +153 -0
  85. data/lib/sapor/regional_data/denmark-20150618.psv +142 -0
  86. data/lib/sapor/regional_data/denmark.rb +128 -0
  87. data/lib/sapor/regional_data/denmark_with_e.rb +128 -0
  88. data/lib/sapor/regional_data/denmark_with_e_and_p.rb +128 -0
  89. data/lib/sapor/regional_data/denmark_with_p.rb +128 -0
  90. data/lib/sapor/regional_data/estonia.rb +88 -0
  91. data/lib/sapor/regional_data/european-union-great-britain-20140522-brexit-chuk.psv +172 -0
  92. data/lib/sapor/regional_data/european-union-great-britain-20140522.psv +146 -0
  93. data/lib/sapor/regional_data/european-union-great-britain-20190523.psv +141 -0
  94. data/lib/sapor/regional_data/european-union-ireland-2014-ia-ri-sd.psv +64 -0
  95. data/lib/sapor/regional_data/european-union-ireland-2014-ia-sd.psv +60 -0
  96. data/lib/sapor/regional_data/european-union-ireland-2014-ia.psv +56 -0
  97. data/lib/sapor/regional_data/european-union-ireland-2014-sd.psv +56 -0
  98. data/lib/sapor/regional_data/european-union-ireland-2014.psv +50 -0
  99. data/lib/sapor/regional_data/european-union-ireland-20190524-ia.psv +58 -0
  100. data/lib/sapor/regional_data/european-union-ireland-20190524.psv +52 -0
  101. data/lib/sapor/regional_data/european_union_27_austria.rb +76 -0
  102. data/lib/sapor/regional_data/european_union_27_croatia.rb +83 -0
  103. data/lib/sapor/regional_data/european_union_27_denmark.rb +77 -0
  104. data/lib/sapor/regional_data/european_union_27_estonia.rb +74 -0
  105. data/lib/sapor/regional_data/european_union_27_finland.rb +74 -0
  106. data/lib/sapor/regional_data/european_union_27_france.rb +84 -0
  107. data/lib/sapor/regional_data/european_union_27_ireland.rb +96 -0
  108. data/lib/sapor/regional_data/european_union_27_ireland_with_ia.rb +97 -0
  109. data/lib/sapor/regional_data/european_union_27_italy.rb +84 -0
  110. data/lib/sapor/regional_data/european_union_27_netherlands.rb +81 -0
  111. data/lib/sapor/regional_data/european_union_27_poland.rb +84 -0
  112. data/lib/sapor/regional_data/european_union_27_romania.rb +78 -0
  113. data/lib/sapor/regional_data/european_union_27_slovakia.rb +80 -0
  114. data/lib/sapor/regional_data/european_union_27_spain.rb +82 -0
  115. data/lib/sapor/regional_data/european_union_27_sweden.rb +76 -0
  116. data/lib/sapor/regional_data/european_union_austria.rb +76 -0
  117. data/lib/sapor/regional_data/european_union_bulgaria.rb +82 -0
  118. data/lib/sapor/regional_data/european_union_croatia.rb +83 -0
  119. data/lib/sapor/regional_data/european_union_cyprus.rb +72 -0
  120. data/lib/sapor/regional_data/european_union_czech_republic.rb +82 -0
  121. data/lib/sapor/regional_data/european_union_denmark.rb +77 -0
  122. data/lib/sapor/regional_data/european_union_estonia.rb +74 -0
  123. data/lib/sapor/regional_data/european_union_finland.rb +74 -0
  124. data/lib/sapor/regional_data/european_union_flanders.rb +74 -0
  125. data/lib/sapor/regional_data/european_union_france.rb +84 -0
  126. data/lib/sapor/regional_data/european_union_french_community_of_belgium.rb +73 -0
  127. data/lib/sapor/regional_data/european_union_germany.rb +86 -0
  128. data/lib/sapor/regional_data/european_union_great_britain.rb +98 -0
  129. data/lib/sapor/regional_data/european_union_greece.rb +77 -0
  130. data/lib/sapor/regional_data/european_union_hungary.rb +76 -0
  131. data/lib/sapor/regional_data/european_union_ireland.rb +96 -0
  132. data/lib/sapor/regional_data/european_union_ireland_with_ia.rb +97 -0
  133. data/lib/sapor/regional_data/european_union_italy.rb +84 -0
  134. data/lib/sapor/regional_data/european_union_latvia.rb +81 -0
  135. data/lib/sapor/regional_data/european_union_lithuania.rb +80 -0
  136. data/lib/sapor/regional_data/european_union_luxembourg.rb +75 -0
  137. data/lib/sapor/regional_data/european_union_malta.rb +71 -0
  138. data/lib/sapor/regional_data/european_union_netherlands.rb +81 -0
  139. data/lib/sapor/regional_data/european_union_northern_ireland.rb +75 -0
  140. data/lib/sapor/regional_data/european_union_poland.rb +84 -0
  141. data/lib/sapor/regional_data/european_union_portugal.rb +75 -0
  142. data/lib/sapor/regional_data/european_union_romania.rb +78 -0
  143. data/lib/sapor/regional_data/european_union_slovakia.rb +81 -0
  144. data/lib/sapor/regional_data/european_union_slovenia.rb +85 -0
  145. data/lib/sapor/regional_data/european_union_spain.rb +82 -0
  146. data/lib/sapor/regional_data/european_union_sweden.rb +76 -0
  147. data/lib/sapor/regional_data/finland-20150419-with-sin.psv +224 -0
  148. data/lib/sapor/regional_data/finland-20150419.psv +212 -0
  149. data/lib/sapor/regional_data/finland.rb +107 -0
  150. data/lib/sapor/regional_data/finland_with_sin.rb +107 -0
  151. data/lib/sapor/regional_data/flanders-2014.psv +96 -0
  152. data/lib/sapor/regional_data/flanders-20190526.psv +87 -0
  153. data/lib/sapor/regional_data/flanders.rb +115 -0
  154. data/lib/sapor/regional_data/france.rb +38 -0
  155. data/lib/sapor/regional_data/greece.rb +92 -0
  156. data/lib/sapor/regional_data/hungary-2014.psv +2104 -0
  157. data/lib/sapor/regional_data/hungary.rb +116 -0
  158. data/lib/sapor/regional_data/iceland-20161029-midflokkurinn.psv +94 -0
  159. data/lib/sapor/regional_data/iceland-20161029.psv +88 -0
  160. data/lib/sapor/regional_data/iceland-20171028-with-j.psv +94 -0
  161. data/lib/sapor/regional_data/iceland-20171028.psv +85 -0
  162. data/lib/sapor/regional_data/iceland.rb +149 -0
  163. data/lib/sapor/regional_data/ireland-20160226-2020-candidates.psv +322 -0
  164. data/lib/sapor/regional_data/ireland-20160226-2020.psv +344 -0
  165. data/lib/sapor/regional_data/ireland-20160226.psv +348 -0
  166. data/lib/sapor/regional_data/ireland.rb +165 -0
  167. data/lib/sapor/regional_data/latvia-20141004-kpv-p-par.psv +109 -0
  168. data/lib/sapor/regional_data/latvia-20141004-kpv-par.psv +103 -0
  169. data/lib/sapor/regional_data/latvia-20141004-kpv.psv +97 -0
  170. data/lib/sapor/regional_data/latvia-20141004.psv +89 -0
  171. data/lib/sapor/regional_data/latvia-20181006.psv +104 -0
  172. data/lib/sapor/regional_data/latvia.rb +111 -0
  173. data/lib/sapor/regional_data/luxembourg-20131020.psv +60 -0
  174. data/lib/sapor/regional_data/luxembourg-20181014.psv +59 -0
  175. data/lib/sapor/regional_data/luxembourg.rb +88 -0
  176. data/lib/sapor/regional_data/netherlands.rb +108 -0
  177. data/lib/sapor/regional_data/norway-20170911.psv +331 -0
  178. data/lib/sapor/regional_data/norway.rb +130 -0
  179. data/lib/sapor/regional_data/norwegian_municipality.rb +68 -0
  180. data/lib/sapor/regional_data/poland-20151025-with-ko-and-l-without-n-po-r-and-zl.psv +321 -0
  181. 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
  182. data/lib/sapor/regional_data/poland-20151025-with-ko-sld-and-wi-without-n-po-and-zl.psv +403 -0
  183. data/lib/sapor/regional_data/poland-20151025-with-sld-and-wi-without-zl.psv +444 -0
  184. data/lib/sapor/regional_data/poland-20151025-with-sld-without-zl.psv +403 -0
  185. data/lib/sapor/regional_data/poland-20151025.psv +403 -0
  186. data/lib/sapor/regional_data/poland.rb +125 -0
  187. data/lib/sapor/regional_data/poland_with_ko_and_l_without_n_po_r_and_zl.rb +122 -0
  188. 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
  189. data/lib/sapor/regional_data/poland_with_ko_sld_and_wi_without_n_po_and_zl.rb +125 -0
  190. data/lib/sapor/regional_data/poland_with_sld_and_wi_without_zl.rb +126 -0
  191. data/lib/sapor/regional_data/poland_with_sld_without_zl.rb +126 -0
  192. data/lib/sapor/regional_data/portugal-20151004-with-a-and-ch-without-paf.psv +438 -0
  193. data/lib/sapor/regional_data/portugal-20151004-with-a-and-il-without-paf.psv +438 -0
  194. data/lib/sapor/regional_data/portugal-20151004-with-a-ch-and-il-without-paf.psv +461 -0
  195. data/lib/sapor/regional_data/portugal-20151004-with-a-without-paf.psv +415 -0
  196. data/lib/sapor/regional_data/portugal-20151004-with-ch-and-il-without-paf.psv +438 -0
  197. data/lib/sapor/regional_data/portugal-20151004-without-paf.psv +392 -0
  198. data/lib/sapor/regional_data/portugal-20151004.psv +370 -0
  199. data/lib/sapor/regional_data/portugal.rb +101 -0
  200. data/lib/sapor/regional_data/portugal_with_a_and_ch_without_paf.rb +92 -0
  201. data/lib/sapor/regional_data/portugal_with_a_and_il_without_paf.rb +92 -0
  202. data/lib/sapor/regional_data/portugal_with_a_ch_and_il_without_paf.rb +92 -0
  203. data/lib/sapor/regional_data/portugal_with_a_without_paf.rb +92 -0
  204. data/lib/sapor/regional_data/portugal_with_ch_and_il_without_paf.rb +92 -0
  205. data/lib/sapor/regional_data/portugal_without_paf.rb +92 -0
  206. data/lib/sapor/regional_data/slovakia.rb +81 -0
  207. data/lib/sapor/regional_data/slovenia.rb +114 -0
  208. data/lib/sapor/regional_data/spain-20160626.psv +619 -0
  209. data/lib/sapor/regional_data/spain.rb +136 -0
  210. data/lib/sapor/regional_data/sweden.rb +92 -0
  211. data/lib/sapor/regional_data/sweden_20140914.rb +89 -0
  212. data/lib/sapor/regional_data/united_kingdom-2015.psv +4358 -0
  213. data/lib/sapor/regional_data/united_kingdom-20170608-brexit-chuk.psv +5154 -0
  214. data/lib/sapor/regional_data/united_kingdom-20170608-brexit.psv +4521 -0
  215. data/lib/sapor/regional_data/united_kingdom-20170608-tig.psv +4529 -0
  216. data/lib/sapor/regional_data/united_kingdom-20170608.psv +3894 -0
  217. data/lib/sapor/regional_data/united_kingdom.rb +94 -0
  218. data/lib/sapor/regional_data/united_kingdom_with_brexit.rb +110 -0
  219. data/lib/sapor/regional_data/united_kingdom_with_brexit_and_chuk.rb +111 -0
  220. data/lib/sapor/regional_data/united_kingdom_with_tig.rb +111 -0
  221. data/lib/sapor/regional_data/utopia.rb +66 -0
  222. data/lib/sapor/regional_data/wallonia-2014.psv +101 -0
  223. data/lib/sapor/regional_data/wallonia-20190526.psv +88 -0
  224. data/lib/sapor/regional_data/wallonia.rb +112 -0
  225. data/lib/sapor/representatives_polychotomy.rb +338 -0
  226. data/lib/sapor/single_district_proportional.rb +75 -0
  227. data/sapor.gemspec +35 -0
  228. data/spec/integration/area_spec.rb +28 -0
  229. data/spec/integration/poll_spec.rb +112 -0
  230. data/spec/integration/sample.poll +8 -0
  231. data/spec/spec_helper.rb +31 -0
  232. data/spec/unit/area_spec.rb +115 -0
  233. data/spec/unit/austria_spec.rb +76 -0
  234. data/spec/unit/belgium_brussels_spec.rb +58 -0
  235. data/spec/unit/belgium_flanders_spec.rb +62 -0
  236. data/spec/unit/belgium_spec.rb +26 -0
  237. data/spec/unit/belgium_wallonia_spec.rb +65 -0
  238. data/spec/unit/binomials_cache_spec.rb +34 -0
  239. data/spec/unit/catalonia_spec.rb +61 -0
  240. data/spec/unit/catalonia_with_vox_spec.rb +62 -0
  241. data/spec/unit/combinations_distribution_spec.rb +241 -0
  242. data/spec/unit/denmark_spec.rb +56 -0
  243. data/spec/unit/denmark_with_e_and_p_spec.rb +58 -0
  244. data/spec/unit/denmark_with_e_spec.rb +57 -0
  245. data/spec/unit/denmark_with_p_spec.rb +57 -0
  246. data/spec/unit/denominators_spec.rb +40 -0
  247. data/spec/unit/dichotomies_spec.rb +154 -0
  248. data/spec/unit/dichotomy_spec.rb +320 -0
  249. data/spec/unit/estonia_spec.rb +65 -0
  250. data/spec/unit/european_union_27_austria_spec.rb +61 -0
  251. data/spec/unit/european_union_27_croatia_spec.rb +60 -0
  252. data/spec/unit/european_union_27_denmark_spec.rb +62 -0
  253. data/spec/unit/european_union_27_estonia_spec.rb +94 -0
  254. data/spec/unit/european_union_27_finland_spec.rb +75 -0
  255. data/spec/unit/european_union_27_france_spec.rb +73 -0
  256. data/spec/unit/european_union_27_ireland_spec.rb +72 -0
  257. data/spec/unit/european_union_27_ireland_with_ia_spec.rb +74 -0
  258. data/spec/unit/european_union_27_italy_spec.rb +69 -0
  259. data/spec/unit/european_union_27_netherlands_spec.rb +81 -0
  260. data/spec/unit/european_union_27_poland_spec.rb +69 -0
  261. data/spec/unit/european_union_27_romania_spec.rb +67 -0
  262. data/spec/unit/european_union_27_slovakia_spec.rb +111 -0
  263. data/spec/unit/european_union_27_spain_spec.rb +130 -0
  264. data/spec/unit/european_union_27_sweden_spec.rb +89 -0
  265. data/spec/unit/european_union_austria_spec.rb +61 -0
  266. data/spec/unit/european_union_bulgaria_spec.rb +97 -0
  267. data/spec/unit/european_union_croatia_spec.rb +59 -0
  268. data/spec/unit/european_union_cyprus_spec.rb +65 -0
  269. data/spec/unit/european_union_czech_republic_spec.rb +125 -0
  270. data/spec/unit/european_union_denmark_spec.rb +61 -0
  271. data/spec/unit/european_union_estonia_spec.rb +93 -0
  272. data/spec/unit/european_union_finland_spec.rb +75 -0
  273. data/spec/unit/european_union_flanders_spec.rb +56 -0
  274. data/spec/unit/european_union_france_spec.rb +73 -0
  275. data/spec/unit/european_union_french_community_of_belgium_spec.rb +61 -0
  276. data/spec/unit/european_union_germany_spec.rb +90 -0
  277. data/spec/unit/european_union_great_britain_spec.rb +87 -0
  278. data/spec/unit/european_union_greece_spec.rb +148 -0
  279. data/spec/unit/european_union_hungary_spec.rb +57 -0
  280. data/spec/unit/european_union_ireland_spec.rb +72 -0
  281. data/spec/unit/european_union_ireland_with_ia_spec.rb +74 -0
  282. data/spec/unit/european_union_italy_spec.rb +69 -0
  283. data/spec/unit/european_union_latvia_spec.rb +76 -0
  284. data/spec/unit/european_union_lithuania_spec.rb +68 -0
  285. data/spec/unit/european_union_luxembourg_spec.rb +63 -0
  286. data/spec/unit/european_union_malta_spec.rb +60 -0
  287. data/spec/unit/european_union_netherlands_spec.rb +81 -0
  288. data/spec/unit/european_union_northern_ireland_spec.rb +66 -0
  289. data/spec/unit/european_union_poland_spec.rb +69 -0
  290. data/spec/unit/european_union_portugal_spec.rb +77 -0
  291. data/spec/unit/european_union_romania_spec.rb +67 -0
  292. data/spec/unit/european_union_slovakia_spec.rb +111 -0
  293. data/spec/unit/european_union_slovenia_spec.rb +77 -0
  294. data/spec/unit/european_union_spain_spec.rb +129 -0
  295. data/spec/unit/european_union_sweden_spec.rb +89 -0
  296. data/spec/unit/finland_spec.rb +65 -0
  297. data/spec/unit/finland_with_sin_spec.rb +67 -0
  298. data/spec/unit/first_past_the_post_spec.rb +54 -0
  299. data/spec/unit/flanders_spec.rb +70 -0
  300. data/spec/unit/france_spec.rb +32 -0
  301. data/spec/unit/greece_spec.rb +118 -0
  302. data/spec/unit/hungary_spec.rb +132 -0
  303. data/spec/unit/iceland_spec.rb +57 -0
  304. data/spec/unit/iceland_with_j_spec.rb +58 -0
  305. data/spec/unit/ireland_2016_spec.rb +62 -0
  306. data/spec/unit/ireland_spec.rb +62 -0
  307. data/spec/unit/largest_remainder_spec.rb +79 -0
  308. data/spec/unit/latvia_spec.rb +62 -0
  309. data/spec/unit/luxembourg_spec.rb +55 -0
  310. data/spec/unit/multi_district_leveled_proportional_spec.rb +49 -0
  311. data/spec/unit/multi_district_proportional_spec.rb +81 -0
  312. data/spec/unit/netherlands_spec.rb +107 -0
  313. data/spec/unit/norway_spec.rb +69 -0
  314. data/spec/unit/norwegian_municipality_spec.rb +89 -0
  315. data/spec/unit/number_formatter_spec.rb +173 -0
  316. data/spec/unit/poland_spec.rb +62 -0
  317. data/spec/unit/poland_with_ko_and_l_without_n_po_r_and_zl_spec.rb +60 -0
  318. 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
  319. data/spec/unit/poland_with_ko_sld_and_wi_without_n_po_and_zl_spec.rb +62 -0
  320. data/spec/unit/poland_with_sld_and_wi_without_zl_spec.rb +63 -0
  321. data/spec/unit/poland_with_sld_without_zl_spec.rb +62 -0
  322. data/spec/unit/poll_spec.rb +110 -0
  323. data/spec/unit/portugal_spec.rb +66 -0
  324. data/spec/unit/portugal_with_a_and_ch_without_paf_spec.rb +68 -0
  325. data/spec/unit/portugal_with_a_and_il_without_paf_spec.rb +68 -0
  326. data/spec/unit/portugal_with_a_ch_and_il_without_paf_spec.rb +69 -0
  327. data/spec/unit/portugal_with_a_without_paf_spec.rb +67 -0
  328. data/spec/unit/portugal_with_ch_and_il_without_paf_spec.rb +68 -0
  329. data/spec/unit/portugal_without_paf_spec.rb +66 -0
  330. data/spec/unit/pseudorandom_multirange_enumerator_spec.rb +82 -0
  331. data/spec/unit/referendum_polychotomy_spec.rb +289 -0
  332. data/spec/unit/representatives_polychotomy_spec.rb +332 -0
  333. data/spec/unit/slovakia_spec.rb +99 -0
  334. data/spec/unit/slovenia_spec.rb +80 -0
  335. data/spec/unit/spain_spec.rb +101 -0
  336. data/spec/unit/sweden_20140914_spec.rb +112 -0
  337. data/spec/unit/sweden_spec.rb +113 -0
  338. data/spec/unit/united_kingdom_spec.rb +65 -0
  339. data/spec/unit/united_kingdom_with_brexit_and_chuk_spec.rb +67 -0
  340. data/spec/unit/united_kingdom_with_brexit_spec.rb +66 -0
  341. data/spec/unit/united_kingdom_with_tig_spec.rb +66 -0
  342. data/spec/unit/wallonia_spec.rb +70 -0
  343. metadata +502 -0
@@ -0,0 +1,73 @@
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
+ #
23
+ # Represents a set of options.
24
+ #
25
+ class Options
26
+ DEFAULT_MAX_ERROR = 0.001
27
+ DEFAULT_MAX_POLYCHOTOMY_ITERATIONS = 2 ** 25
28
+ DEFAULT_MIN_DICHOTOMIES_ITERATIONS = 0
29
+ DEFAULT_MIN_POLYCHOTOMY_ITERATIONS = 2 ** 20
30
+
31
+ MAX_ERROR_KEY = 'emx'
32
+ MAX_POLYCHOTOMY_ITERATIONS_KEY = 'pmx'
33
+ MIN_DICHOTOMIES_ITERATIONS_KEY = 'dmn'
34
+ MIN_POLYCHOTOMY_ITERATIONS_KEY = 'pmn'
35
+
36
+ FLOAT_OPTIONS = [MAX_ERROR_KEY]
37
+ INTEGER_OPTIONS = [MAX_POLYCHOTOMY_ITERATIONS_KEY, MIN_DICHOTOMIES_ITERATIONS_KEY, MIN_POLYCHOTOMY_ITERATIONS_KEY]
38
+
39
+ def initialize(arguments)
40
+ @hash = { MAX_ERROR_KEY => DEFAULT_MAX_ERROR,
41
+ MAX_POLYCHOTOMY_ITERATIONS_KEY => DEFAULT_MAX_POLYCHOTOMY_ITERATIONS,
42
+ MIN_DICHOTOMIES_ITERATIONS_KEY => DEFAULT_MIN_DICHOTOMIES_ITERATIONS,
43
+ MIN_POLYCHOTOMY_ITERATIONS_KEY => DEFAULT_MIN_POLYCHOTOMY_ITERATIONS }
44
+ arguments.each do | argument |
45
+ key_value = argument[1..-1].split('=')
46
+ key = key_value.first
47
+ value = key_value.last
48
+ if INTEGER_OPTIONS.include?(key)
49
+ value = value.to_i
50
+ elsif FLOAT_OPTIONS.include?(key)
51
+ value = value.to_f
52
+ end
53
+ @hash[key] = value
54
+ end
55
+ end
56
+
57
+ def max_error
58
+ @hash[MAX_ERROR_KEY]
59
+ end
60
+
61
+ def max_polychotomy_iterations
62
+ @hash[MAX_POLYCHOTOMY_ITERATIONS_KEY]
63
+ end
64
+
65
+ def min_dichotomies_iterations
66
+ @hash[MIN_DICHOTOMIES_ITERATIONS_KEY]
67
+ end
68
+
69
+ def min_polychotomy_iterations
70
+ @hash[MIN_POLYCHOTOMY_ITERATIONS_KEY]
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,282 @@
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
+ require 'yaml'
20
+
21
+ module Sapor
22
+ OTHER = 'Other'.freeze
23
+
24
+ #
25
+ # Represents a poll.
26
+ #
27
+ class Poll
28
+ include NumberFormatter
29
+ attr_reader :area, :logger, :type
30
+
31
+ AREA_KEY = 'Area'.freeze
32
+
33
+ BELGIAN_AREAS = [BelgiumBrussels.instance, BelgiumFlanders.instance,
34
+ BelgiumWallonia.instance, Flanders.instance,
35
+ Wallonia.instance].freeze
36
+ DANISH_AREAS = [Denmark.instance, DenmarkWithE.instance,
37
+ DenmarkWithEAndP.instance, DenmarkWithP.instance].freeze
38
+ EUROPEAN_UNION_AREAS = [EuropeanUnion27Austria.instance,
39
+ EuropeanUnion27Croatia.instance,
40
+ EuropeanUnion27Denmark.instance,
41
+ EuropeanUnion27Estonia.instance,
42
+ EuropeanUnion27Finland.instance,
43
+ EuropeanUnion27France.instance,
44
+ EuropeanUnion27Ireland.instance,
45
+ EuropeanUnion27IrelandWithIa.instance,
46
+ EuropeanUnion27Italy.instance,
47
+ EuropeanUnion27Netherlands.instance,
48
+ EuropeanUnion27Poland.instance,
49
+ EuropeanUnion27Romania.instance,
50
+ EuropeanUnion27Slovakia.instance,
51
+ EuropeanUnion27Spain.instance,
52
+ EuropeanUnion27Sweden.instance,
53
+ EuropeanUnionAustria.instance,
54
+ EuropeanUnionBulgaria.instance,
55
+ EuropeanUnionCroatia.instance,
56
+ EuropeanUnionCyprus.instance,
57
+ EuropeanUnionCzechRepublic.instance,
58
+ EuropeanUnionDenmark.instance,
59
+ EuropeanUnionEstonia.instance,
60
+ EuropeanUnionFinland.instance,
61
+ EuropeanUnionFlanders.instance,
62
+ EuropeanUnionFrance.instance,
63
+ EuropeanUnionFrenchCommunityOfBelgium.instance,
64
+ EuropeanUnionGermany.instance,
65
+ EuropeanUnionGreatBritain.instance,
66
+ EuropeanUnionGreece.instance,
67
+ EuropeanUnionHungary.instance,
68
+ EuropeanUnionIreland.instance,
69
+ EuropeanUnionIrelandWithIa.instance,
70
+ EuropeanUnionItaly.instance,
71
+ EuropeanUnionLatvia.instance,
72
+ EuropeanUnionLithuania.instance,
73
+ EuropeanUnionLuxembourg.instance,
74
+ EuropeanUnionMalta.instance,
75
+ EuropeanUnionNetherlands.instance,
76
+ EuropeanUnionNorthernIreland.instance,
77
+ EuropeanUnionPoland.instance,
78
+ EuropeanUnionPortugal.instance,
79
+ EuropeanUnionRomania.instance,
80
+ EuropeanUnionSlovakia.instance,
81
+ EuropeanUnionSlovenia.instance,
82
+ EuropeanUnionSpain.instance,
83
+ EuropeanUnionSweden.instance].freeze
84
+ NORWEGIAN_AREAS = [Norway.instance, NorwegianMunicipality::BERGEN,
85
+ NorwegianMunicipality::OSLO,
86
+ NorwegianMunicipality::TRONDHEIM].freeze
87
+ POLISH_AREAS = [Poland.instance,
88
+ PolandWithKoAndLWithoutNPoRAndZl.instance,
89
+ PolandWithKoKonfKpLAndZpWithoutKK15NPisPoPslRAndZl.instance,
90
+ PolandWithKoSldAndWiWithoutNPoAndZl.instance,
91
+ PolandWithSldAndWiWithoutZL.instance,
92
+ PolandWithSldWithoutZL.instance].freeze
93
+ PORTUGUESE_AREAS = [Portugal.instance,
94
+ PortugalWithAAndChWithoutPaf.instance,
95
+ PortugalWithAAndIlWithoutPaf.instance,
96
+ PortugalWithAChAndIlWithoutPaf.instance,
97
+ PortugalWithAWithoutPaf.instance,
98
+ PortugalWithChAndIlWithoutPaf.instance,
99
+ PortugalWithoutPaf.instance].freeze
100
+ AREAS_MAP = {}
101
+ (BELGIAN_AREAS + DANISH_AREAS + EUROPEAN_UNION_AREAS + NORWEGIAN_AREAS + \
102
+ POLISH_AREAS + PORTUGUESE_AREAS + \
103
+ [Austria.instance, Catalonia.instance, CataloniaWithVox.instance,
104
+ Estonia.instance, Finland.instance, FinlandWithSin.instance,
105
+ France.instance, Greece.instance, Hungary.instance, Iceland.instance,
106
+ IcelandWithJ.instance, Ireland.instance, Latvia.instance,
107
+ Luxembourg.instance, Netherlands.instance, Slovakia.instance,
108
+ Slovenia.instance, Spain.instance, Sweden.instance,
109
+ Sweden20140914.instance, UnitedKingdom.instance,
110
+ UnitedKingdomWithBrexit.instance, UnitedKingdomWithBrexitAndChuk.instance,
111
+ UnitedKingdomWithTig.instance, Utopia.instance]).map do |area|
112
+ AREAS_MAP[area.area_code] = area
113
+ end
114
+
115
+ TYPE_KEY = 'Type'.freeze
116
+ REFERENDUM_TYPE_VALUE = 'Referendum'.freeze
117
+ ELECTION_TYPE_VALUE = 'Election'.freeze
118
+
119
+ DEFAULT_CONFIDENCE_LEVEL = 0.95
120
+
121
+ def initialize(filename, metadata, results)
122
+ @filename = filename
123
+ @logger = LogFacade.create_logger
124
+ @area_code = metadata.delete(AREA_KEY)
125
+ @area = Poll.lookup_area(@area_code)
126
+ @type = metadata.delete(TYPE_KEY)
127
+ @results = interpret(results)
128
+ end
129
+
130
+ def analyze(options)
131
+ analyze_as_dichotomies(options)
132
+ analyze_as_polychotomy(options)
133
+ @logger.info('Done.')
134
+ end
135
+
136
+ def continue_analysis(options)
137
+ @logger = LogFacade.create_logger
138
+ @logger.info('Continuing the analysis as a polychotomy...')
139
+ @area = Poll.lookup_area(@area_code)
140
+ @analysis.revive_volatile_fields(@logger)
141
+ analyze_until_convergence(options)
142
+ @logger.info('Done.')
143
+ end
144
+
145
+ def confidence_interval(choice, level = DEFAULT_CONFIDENCE_LEVEL)
146
+ @analysis.confidence_interval(choice, level) unless @analysis.nil?
147
+ end
148
+
149
+ def most_probable_fraction(choice)
150
+ @analysis.most_probable_fraction(choice) unless @analysis.nil?
151
+ end
152
+
153
+ def most_probable_value(choice)
154
+ @analysis.most_probable_value(choice) unless @analysis.nil?
155
+ end
156
+
157
+ def result(choice)
158
+ @results[choice]
159
+ end
160
+
161
+ def encode_with(coder)
162
+ (instance_variables - [:@area, :@logger]).each do |var|
163
+ var = var.to_s
164
+ coder[var.gsub('@', '')] = eval(var)
165
+ end
166
+ end
167
+
168
+ def self.lookup_area(area_code)
169
+ AREAS_MAP[area_code]
170
+ end
171
+
172
+ private
173
+
174
+ def self.line_to_hash(line, current, results)
175
+ if line.chomp.eql?('==')
176
+ current = results
177
+ else
178
+ elements = line.chomp.split('=')
179
+ current[elements.first] = elements.last
180
+ end
181
+ current
182
+ end
183
+
184
+ def self.as_hashes(lines)
185
+ metadata = {}
186
+ results = {}
187
+ current = metadata
188
+ lines.each do |line|
189
+ current = line_to_hash(line, current, results)
190
+ end
191
+ [metadata, results]
192
+ end
193
+
194
+ def self.from_lines(filename, lines)
195
+ hashes = as_hashes(lines)
196
+ metadata = hashes.first
197
+ results = hashes.last
198
+ new(filename, metadata, results)
199
+ end
200
+
201
+ def self.from_file(filename)
202
+ from_lines(filename, File.open(filename))
203
+ end
204
+
205
+ def interpret(results)
206
+ interpreted = {}
207
+ results.each_pair do |key, value|
208
+ interpreted[key] = value.to_i
209
+ end
210
+ interpreted
211
+ end
212
+
213
+ def population_size
214
+ @area.population_size
215
+ end
216
+
217
+ def referendum?
218
+ @type == REFERENDUM_TYPE_VALUE
219
+ end
220
+
221
+ def threshold
222
+ if referendum?
223
+ 0.5
224
+ else
225
+ @area.threshold
226
+ end
227
+ end
228
+
229
+ def analyze_until_convergence(options)
230
+ while should_continue_analysis?(@analysis, options)
231
+ @analysis.refine
232
+ @logger.info(@analysis.report)
233
+ @logger.info('Error estimate: ε ≤ ' +
234
+ three_digits_percentage(@analysis.error_estimate) +
235
+ '.')
236
+ @logger.info(@analysis.progress_report)
237
+ @analysis.write_outputs(@filename)
238
+ save_state
239
+ end
240
+ end
241
+
242
+ def should_continue_analysis?(analysis, options)
243
+ analysis.kind_of?(Dichotomies) \
244
+ && (options.min_dichotomies_iterations > analysis.size \
245
+ || analysis.error_estimate > options.max_error) \
246
+ || analysis.kind_of?(Polychotomy) \
247
+ && options.max_polychotomy_iterations > analysis.no_of_simulations \
248
+ && (options.min_polychotomy_iterations > analysis.no_of_simulations \
249
+ || analysis.error_estimate > options.max_error)
250
+ end
251
+
252
+ def analyze_as_dichotomies(options)
253
+ @logger.info('Analyzing as a set of dichotomies...')
254
+ @analysis = Dichotomies.new(@results, population_size, threshold)
255
+ analyze_until_convergence(options)
256
+ end
257
+
258
+ def analyze_as_polychotomy(options)
259
+ @logger.info('Analyzing as a polychotomy...')
260
+ if referendum?
261
+ @analysis = ReferendumPolychotomy.new(@results, @area, @analysis,
262
+ options.max_error)
263
+ else
264
+ @analysis = RepresentativesPolychotomy.new(@results, @area, @analysis,
265
+ options.max_error, @logger)
266
+ end
267
+ analyze_until_convergence(options)
268
+ end
269
+
270
+ def save_state
271
+ new_yaml_file = @filename.gsub('.poll', '-state-new.yaml')
272
+ open(new_yaml_file, 'w') do |file|
273
+ file.write(to_yaml)
274
+ end
275
+ yaml_file = @filename.gsub('.poll', '-state.yaml')
276
+ old_yaml_file = @filename.gsub('.poll', '-state-old.yaml')
277
+ File.delete(old_yaml_file) if File.exist?(old_yaml_file)
278
+ File.rename(yaml_file, old_yaml_file) if File.exist?(yaml_file)
279
+ File.rename(new_yaml_file, yaml_file)
280
+ end
281
+ end
282
+ end
@@ -0,0 +1,200 @@
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
+ # Superclass for polychotomies.
23
+ #
24
+ class Polychotomy
25
+ attr_reader :error_estimate, :no_of_data_points, :no_of_simulations
26
+
27
+ def initialize(results, area, dichotomies, max_error)
28
+ initialize_static_information(results, area, dichotomies, max_error)
29
+ initialize_calculation_information
30
+ end
31
+
32
+ def most_probable_fraction(key)
33
+ if @no_of_simulations == 0
34
+ nil
35
+ else
36
+ calculate_most_probable_fraction(key, @votes)
37
+ end
38
+ end
39
+
40
+ def most_probable_value(key)
41
+ if @no_of_simulations == 0
42
+ nil
43
+ else
44
+ @votes[key].most_probable_value
45
+ end
46
+ end
47
+
48
+ def range(choice)
49
+ @ranges[choice]
50
+ end
51
+
52
+ def space_size
53
+ @enum.size
54
+ end
55
+
56
+ def encode_with(coder)
57
+ (instance_variables - [:@area, :@enum, :@logger]).each do |var|
58
+ var = var.to_s
59
+ coder[var.gsub('@', '')] = eval(var)
60
+ end
61
+ end
62
+
63
+ def revive_volatile_fields(logger = nil)
64
+ @area = Poll.lookup_area(@area_code)
65
+ @enum = create_enumerator(@ranges)
66
+ @logger = logger
67
+ 1.upto(@no_of_data_points).each { |i| @enum.next() }
68
+ end
69
+
70
+ private
71
+
72
+ def calculate_most_probable_fraction(key, votes)
73
+ votes[key].most_probable_value.to_f / @area.population_size
74
+ end
75
+
76
+ def calculate_most_probable_rounded_fraction(key, votes)
77
+ votes[key].most_probable_rounded_fraction(@area.population_size)
78
+ end
79
+
80
+ def create_comparisons(choices)
81
+ comparisons = {}
82
+ choices.each do |a|
83
+ choices.each do |b|
84
+ comparisons[a + '>' + b] = 0.to_lf
85
+ end
86
+ end
87
+ comparisons
88
+ end
89
+
90
+ def create_enumerator(ranges)
91
+ range_sizes = ranges.values.map(&:size)
92
+ PseudoRandomMultiRangeEnumerator.new(range_sizes).each
93
+ end
94
+
95
+ def create_rankings(choices)
96
+ rankings = {}
97
+ choices.each do |choice|
98
+ 1.upto(choices.size).each do |i|
99
+ rankings[choice + '@' + (i - 1).to_s] = 0.to_lf
100
+ end
101
+ end
102
+ rankings
103
+ end
104
+
105
+ def extract_ranges_from_dichotomies(dichotomies, max_error)
106
+ ranges = {}
107
+ level = 1 - (max_error**2)
108
+ @choices.each do |choice|
109
+ unless choice == OTHER
110
+ ranges[choice] = dichotomies.confidence_interval_values(choice,
111
+ level).sort
112
+ end
113
+ end
114
+ ranges
115
+ end
116
+
117
+ def initialize_calculation_information
118
+ @enum = create_enumerator(@ranges)
119
+ @no_of_simulations = 0
120
+ @no_of_data_points = 0
121
+ @combinations_sum = 0.to_lf
122
+ @error_estimate = 1.0
123
+ @votes = create_new_votes_distributions
124
+ end
125
+
126
+ def initialize_static_information(results, area, dichotomies, max_error)
127
+ @results = results
128
+ @area = area
129
+ @area_code = area.area_code
130
+ @choices = results.keys
131
+ @comparisons = create_comparisons(@choices)
132
+ @rankings = create_rankings(@choices)
133
+ @ranges = extract_ranges_from_dichotomies(dichotomies, max_error)
134
+ end
135
+
136
+ def larger_than(a, b)
137
+ probability = @comparisons[a + '>' + b] / @combinations_sum
138
+ probability.mantissa * (10**probability.exponent)
139
+ end
140
+
141
+ def most_probable_rounded_fraction(key)
142
+ if @no_of_simulations == 0
143
+ nil
144
+ else
145
+ calculate_most_probable_rounded_fraction(key, @votes)
146
+ end
147
+ end
148
+
149
+ def next_data_point
150
+ indexes = @enum.next
151
+ data_point = {}
152
+ indexes.each_with_index do |ix, i|
153
+ data_point[@ranges.keys[i]] = @ranges.values[i][ix]
154
+ end
155
+ data_point[OTHER] = @area.population_size - data_point.values.inject(:+)
156
+ data_point
157
+ end
158
+
159
+ def ranking(choice, i)
160
+ probability = @rankings[choice + '@' + i.to_s] / @combinations_sum
161
+ probability.mantissa * (10**probability.exponent)
162
+ end
163
+
164
+ def result(choice)
165
+ @results[choice].to_f / @results.values.inject(:+)
166
+ end
167
+
168
+ def sort_choices_by_result
169
+ sorted_choices = @choices.reject { |choice| choice == OTHER }
170
+ sorted_choices.sort do |a, b|
171
+ comparison = result(b) <=> result(a)
172
+ if comparison == 0
173
+ a <=> b
174
+ else
175
+ comparison
176
+ end
177
+ end
178
+ end
179
+
180
+ def write_rankings(filename)
181
+ ci_filename = filename.gsub('.poll', '-polychotomy-rankings.psv')
182
+ File.open(ci_filename, 'w') do |file|
183
+ file.puts('Choice | ' + 0.upto(@choices.size - 1).map {|i| i + 1}.join(' | '))
184
+ @choices.each do | choice |
185
+ file.puts(choice + ' | ' + 0.upto(@choices.size - 1).map {|i| ranking(choice, i)}.join(' | '))
186
+ end
187
+ end
188
+ end
189
+
190
+ def write_state_summary(filename)
191
+ state_summary_filename = filename.gsub('.poll', '_state_summary.txt')
192
+ File.open(state_summary_filename, 'w') do |file|
193
+ file.puts("ErrorEstimate=#{@error_estimate}")
194
+ file.puts("NumberOfSimulations=#{@no_of_simulations}")
195
+ file.puts("NumberOfDataPoints=#{@no_of_data_points}")
196
+ file.puts("SpaceSize=#{space_size}")
197
+ end
198
+ end
199
+ end
200
+ end