· 6 years ago · May 13, 2019, 02:06 AM
1# -*- coding: utf-8 -*-
2"""
3Created on Thu May 2 09:39:37 2019
4
5@author: iqbal
6"""
7
8"""
9Untuk menyimulasikan proses PEMILU dan penghitungan suara ini kita akan menyiapkan dua class:
10 - Voter = yang bertugas memilih salah satu kandidat (kandidat Belalang(01) atau kandidat Kupu-kupu(02))
11 kandidat Kupu-kupu lebih unggul dengan perbandingan 56:44, jadi kemungkinan voter untuk memilihnya adalah sekitar 56%
12 - TPS = bertugas menyimpan data hasil pilihan dari para Voter.
13
14Data suara yang masuk akan kita simpan di database bernama simulasi_tps.db supaya mudah jika ingin dilihat di kemudian hari
15Di dalam database tersebut ada dua tabel:
16 - tps_tbl = menyimpan data:
17 - count_1 : jumlah suara yang memilih Belalang
18 - count_2 : jumlah suara yang memilih Kupu-kupu
19 - input_tbl = menyimpan data hasil penghitungan suara per batch.
20
21Pada simulasi ini disimulasikan tiap hari akan masuk data dari beberapa batch ( variabel input_per_hari )
22Seperti pada kejadian nyata, ada kemungkinan data yang masuk tidak selalu konstan. Saat-saat tertentu data yang masuk lebih banyak dari saat lainnya.
23Ini disimulasikan dengan variabel-variabel berawalan 'flux_'
24Jumlah TPS (variabel num_of_tps ) dan max_voter_per_tps dibuat mirip dengan keadaan nyata.
25
26Ada tiga tahap yang terjadi di sini, sudah dinotasikan dalam comment di bawah:
27 1. Proses Voting
28 2. Proses input data dari obyek TPS ke database
29 3. Rekapitulasi data secara harian dari database
30"""
31
32import numpy as np
33import time
34import random
35import sqlite3
36import matplotlib.pyplot as plt
37
38
39# definisikan variabel-variabel
40max_voter_per_tps = 300
41num_of_tps = 813350
42#num_of_tps = 100000 # for test only
43chance_1 = 44
44chance_2 =56
45count_1 = 0
46count_2 = 0
47total_voter = 0
48db_name = "simulasi_tps.db"
49tps_table_name = "tps_tbl"
50
51
52
53
54# definisikan class-class
55class voter:
56 def __init__(self, chance_1, chance_2):
57 self.chance_1 = chance_1
58 self.chance_2 = chance_2
59 v = random.randint(0,self.chance_1+self.chance_2)
60 if v > self.chance_1:
61 self.voted_for = 2
62 else:
63 self.voted_for = 1
64
65class tps:
66 def __init__(self, voter_per_tps):
67 flux_num_of_voter = 0.09 #fluktuasi jumlah voter di TPS
68 self.num_of_voter = 300 - random.randint(0, voter_per_tps*flux_num_of_voter)
69 def start_vote(self):
70 vote_list = []
71 count_1 = 0
72 count_2 = 0
73 for vt in range(1, self.num_of_voter):
74 this_voter = voter(chance_1, chance_2)
75 vote_list.append(this_voter.voted_for)
76 if vote_list[vt-1] == 1:
77 count_1 = count_1+1
78 else:
79 count_2 = count_2+1
80 self.count_1 = count_1
81 self.count_2 = count_2
82
83# siapkan database untuk simpan data voter
84try:
85 conn = sqlite3.connect(db_name)
86 c = conn.cursor()
87 sql_create_tbl = 'create table if not exists ' + tps_table_name + ' (id integer primary key, count_1 integer, count_2 integer, total_votes integer)'
88
89 c.execute(sql_create_tbl)
90 print("DATABASE CONNECTED FOR VOTING")
91except Error as e:
92 print(e)
93
94
95
96######## 1. Proses Voting ############################################################################
97# mari kita mulai voting
98tps_result_list = []
99for tps_no in range(0, num_of_tps): # proses voting dilakukan sejumlah TPS yang ada
100 this_tps = tps(max_voter_per_tps)
101 this_tps.start_vote() # mulai proses voting
102 count_1 = count_1+this_tps.count_1 # jumlah pemilih 1
103 count_2 = count_2+this_tps.count_2 # jumlah pemilih 2
104 this_tps_result = [this_tps.count_1, this_tps.count_2] # hasil voting di TPS ini
105 tps_result_list.append(this_tps_result) # masukkan hasil voting ke list
106 #sql_insert_tps_rec = "INSERT INTO "+tps_table_name+" VALUES ("+str(this_tps.count_1)+","+str(this_tps.count_2)+")"
107 c.execute("INSERT INTO "+tps_table_name+"(id, count_1, count_2, total_votes) VALUES (?,?,?,?)", (None, this_tps.count_1, this_tps.count_2, this_tps.count_1+this_tps.count_2))
108
109conn.commit() # commit data ke db
110
111#print(str(tps_result_list))
112print("count 1: "+str(count_1)+" , count 2: "+str(count_2))
113percent_1 = count_1 / (count_1+count_2)*100
114percent_2 = count_2 / (count_1+count_2)*100
115print("1 : "+str(percent_1)+"%, 2: "+str(percent_2)+"%")
116print("---- SIMULASI PROSES VOTING DONE -----")
117
118# tutup koneksi ke database
119conn.close()
120print("DATABASE DISCONNECTED")
121
122######## 2. Proses input data dari obyek TPS ke database ############################################################################
123tps_per_input = 10000
124flux_per_input = 0.8 #fluktuasi jumlah data tps yang diinput per input
125input_per_hari = 12 #berapa kali dalam sehari input dilakukan
126start_day = 1
127num_tps_input = 0 #jumlah tps yang sudah diinput
128
129
130# siapkan tabel pada database untuk simpan data
131try:
132 conn = sqlite3.connect(db_name)
133 c = conn.cursor()
134 input_table_name = "input_tbl"
135 sql_create_input_tbl = 'create table if not exists ' + input_table_name + ' (id integer primary key, count_1_this_input integer, count_2_this_input integer, total_votes_this_input integer, tps_index_start integer, tps_index_end integer, total_tps_this_input integer)'
136 c.execute(sql_create_input_tbl)
137 print("DATABASE CONNECTED FOR INPUT")
138except Error as e:
139 print(e)
140
141
142while num_tps_input < num_of_tps: #ulangi proses selama masih ada tps yang belum diinput
143 # start input process
144 num_tps_this_input = random.randrange(int(tps_per_input - tps_per_input * flux_per_input), int(tps_per_input + tps_per_input * flux_per_input), 1)
145 if num_tps_this_input + num_tps_input <= num_of_tps: #supaya jumlah TPS tercatat tidak melebihi jumlah total TPS
146 num_tps_this_input = num_tps_this_input
147 else:
148 num_tps_this_input = num_of_tps - num_tps_input
149
150 # persiapkan counters
151 count_1_this_input = 0
152 count_2_this_input = 0
153 count_total_this_input = 0
154 count_tps_this_input = 0
155
156 # ID TPS yang diambil datanya dari database
157 ids_to_get = []
158 ids_to_get_start = num_tps_input + 1
159 ids_to_get_end = num_tps_input + num_tps_this_input
160 for tps_id in range(ids_to_get_start, ids_to_get_end):
161
162 # start record process
163 #print("tps_id: "+str(tps_id))
164 #get data from db
165 c = conn.cursor()
166 c.execute("SELECT * FROM "+tps_table_name+" WHERE id=?", (tps_id,))
167 row = c.fetchone()
168 #print(row)
169 count_1_this_input += row[1]
170 count_2_this_input += row[2]
171 count_tps_this_input +=1
172 count_total_this_input += (row[1] + row[2])
173 num_tps_input = num_tps_input + num_tps_this_input # tambahkan catatan berapa jumlah TPS yang sudah diinput
174 c.execute("INSERT INTO "+input_table_name+"(id, count_1_this_input, count_2_this_input, total_votes_this_input, tps_index_start, tps_index_end, total_tps_this_input) VALUES (?,?,?,?,?,?,?)", (None, count_1_this_input, count_2_this_input, count_total_this_input, ids_to_get_start, ids_to_get_end, num_tps_this_input))
175 #print("num of TPS this input: "+str(num_tps_this_input))
176 #print("num of TPS already input: "+str(num_tps_input))
177
178conn.commit() # commit data ke db
179
180
181
182######## 3. Rekapitulasi data secara harian dari database ############################################################################
183last_recapped_input_index = 0
184recap_daily = []
185c.execute("SELECT * FROM "+input_table_name) #download data input dari database
186rows = c.fetchall()
187count_1_total = 0
188count_2_total = 0
189count_all_total = 0
190count_tps_total = 0
191days_list = []
192
193for row in rows:
194 print(row)
195
196while last_recapped_input_index < len(rows): # masukkan data yang sudah diinput berdasarkan hari
197 input_per_hari = random.randint(2, input_per_hari) #asumsi data yang dimasukkan tidak konstan kecepatannya
198
199 if len(rows) - last_recapped_input_index > input_per_hari:
200 input_per_hari = input_per_hari
201 else:
202 input_per_hari = len(rows) - last_recapped_input_index
203
204
205 for c in range (last_recapped_input_index,last_recapped_input_index+input_per_hari):
206 print("rows["+str(c)+"] : "+str(rows[c]))
207 count_1 = rows[c][1]
208 count_2 = rows[c][2]
209 count_all = rows[c][3]
210 count_tps = rows[c][6]
211 count_1_total += count_1
212 count_2_total += count_2
213 count_all_total += count_all
214 count_tps_total += count_tps
215 last_recapped_input_index += 1
216
217 count_1_up_to_today = count_1_total
218 count_2_up_to_today = count_2_total
219 count_all_up_to_today = count_all_total
220
221 days_list.append([count_1_up_to_today, count_2_up_to_today, count_all_up_to_today, count_tps_total])
222
223print("Akumulasi per hari========================")
224
225
226akumulasi_count_1 = []
227akumulasi_count_2 = []
228akumulasi_count_all = []
229akumulasi_count_tps =[]
230
231for id_d, day in enumerate(days_list):
232 print("day "+str(id_d))
233 print(day)
234 akumulasi_count_1.append(day[0])
235 akumulasi_count_2.append(day[1])
236 akumulasi_count_all.append(day[2])
237 akumulasi_count_tps.append(day[3])
238
239plt.figure(figsize=(20,15))
240plt.plot(akumulasi_count_1, 'b-')
241plt.plot(akumulasi_count_2,'r-')
242#plt.plot(akumulasi_count_all,'k-')
243plt.ylabel('jumlah suara')
244plt.xlabel('hari penghitungan suara')
245text_string = "JUMLAH VOTE\nBELALANG: "+str(akumulasi_count_1[-1])+"("+str(akumulasi_count_1[-1]/akumulasi_count_all[-1]*100)+"% )\nKUPU-KUPU: "+str(akumulasi_count_2[-1])+"("+str(akumulasi_count_2[-1]/akumulasi_count_all[-1]*100)+"% )"
246#print("JUMLAH VOTE BELALANG: "+str(akumulasi_count_1[-1])+"("+str(akumulasi_count_1[-1]/akumulasi_count_all[-1]*100)+"% )")
247#print("JUMLAH VOTE KUPU-KUPU: "+str(akumulasi_count_2[-1])+"("+str(akumulasi_count_2[-1]/akumulasi_count_all[-1]*100)+"% )")
248print(text_string)
249plt.text(1, 140000000, text_string, style='normal', fontsize=15, bbox={'facecolor': 'yellow', 'alpha': 0.1, 'pad': 10})
250plt.show()
251
252
253# tutup koneksi ke database
254conn.close()
255print("DATABASE DISCONNECTED")