6
6
from ddm .models .core import DonationProject , QuestionnaireResponse , DataDonation , DonationBlueprint
7
7
from ddm .models .serializers import ResponseSerializer , DonationSerializer
8
8
9
+ from .utils import insta_data
10
+
9
11
10
12
class InstagramStatistics (models .Model ):
11
13
name = models .CharField (max_length = 30 )
12
14
15
+ # Follow counts
16
+ follow_counts = models .JSONField (default = None , null = True )
17
+
13
18
# Vote counts
14
19
biodiversity_counts = models .JSONField (default = None , null = True )
15
20
pension_counts = models .JSONField (default = None , null = True )
@@ -18,11 +23,41 @@ class InstagramStatistics (models.Model):
18
23
party_counts = models .JSONField (default = None , null = True )
19
24
20
25
# Use counts
21
- social_media_use = models .JSONField ()
26
+ social_media_use = models .JSONField (default = None , null = True )
22
27
23
28
last_updated = models .DateTimeField (null = True , blank = True )
24
29
project_pk = models .IntegerField (default = 0 )
25
30
31
+ def update_statistics (self ):
32
+ new_responses = self .get_responses ()
33
+ new_donations = self .get_blueprint_donations (settings .BP_ID_FOLLOWED_ACCOUNTS )
34
+
35
+ self .update_followed_accounts (new_donations )
36
+ self .update_vote_counts (new_responses ) # bio & pension
37
+ self .update_party_graphs (new_responses , new_donations )
38
+ self .last_updated = datetime .now ()
39
+ self .save ()
40
+
41
+ def update_followed_accounts (self , donations = None , bp_pk = None ):
42
+ if donations is None :
43
+ donations = self .get_blueprint_donations (settings .BP_ID_FOLLOWED_ACCOUNTS )
44
+
45
+ insta_accounts = insta_data .load_political_account_list ()
46
+ results = []
47
+ for p , d in donations .items ():
48
+ data = {'Gefolgte Kanäle Instagram' : [d ]}
49
+ followed_accounts = insta_data .get_follows_insta (data , insta_accounts )
50
+ if followed_accounts :
51
+ results .append (followed_accounts .copy ())
52
+
53
+ if self .follow_counts is None :
54
+ self .follow_counts = insta_data .TYPES_DICT_PLACEHOLDER .copy ()
55
+
56
+ for r in results :
57
+ for k in r .keys ():
58
+ self .follow_counts [k ].append (len (r [k ]))
59
+ return
60
+
26
61
def update_vote_counts (self , responses = None ):
27
62
if responses is None :
28
63
responses = self .get_responses ()
@@ -51,10 +86,13 @@ def update_bio_count(self, responses, result_dummy, value_map):
51
86
result = self .biodiversity_counts .copy ()
52
87
53
88
var = 'vote-1'
54
- for response in responses :
55
- # TODO: Add check that participant has answered question; otherwise skip
56
- vote = response [var ]
57
- result [value_map [vote ]] += 1
89
+ for p , r in responses .items ():
90
+ if var in r .keys ():
91
+ vote = r [var ]
92
+ else :
93
+ continue
94
+ if vote in value_map .keys ():
95
+ result [value_map [vote ]] += 1
58
96
self .biodiversity_counts = result
59
97
return
60
98
@@ -65,10 +103,13 @@ def update_pension_count(self, responses, result_dummy, value_map):
65
103
result = self .pension_counts .copy ()
66
104
67
105
var = 'vote-2'
68
- for response in responses :
69
- # TODO: Add check that participant has answered question; otherwise skip
70
- vote = response [var ]
71
- result [value_map [vote ]] += 1
106
+ for p , r in responses .items ():
107
+ if var in r .keys ():
108
+ vote = r [var ]
109
+ else :
110
+ continue
111
+ if vote in value_map .keys ():
112
+ result [value_map [vote ]] += 1
72
113
self .pension_counts = result
73
114
return
74
115
@@ -88,25 +129,40 @@ def update_party_graphs(self, responses=None, donations=None, bp_pk=None):
88
129
'FDP' : scale_dummy .copy ()
89
130
}
90
131
91
- for response in responses :
92
- # get participant id
93
- participant = None
94
- # Get var political left/right
95
- var = 'lrsp'
96
- # Check if participant has answered the question
97
- # TODO: Add check that participant has answered question; otherwise skip
98
- pol_stance = response [var ]
132
+ for participant , response in responses .items ():
133
+ if not (participant in responses .keys () and participant in donations .keys ()):
134
+ continue
99
135
100
- # get donation belonging to response
101
- response_donation = None
102
- # compute
103
-
104
-
105
- # SP
106
- # Mitte
107
- # SVP
108
- # FDP
109
- pass
136
+ var = 'lrsp'
137
+ if var in response .keys ():
138
+ pol_stance = response [var ]
139
+ else :
140
+ continue
141
+
142
+ valid_responses = [str (i ) for i in range (1 , 11 )]
143
+ if pol_stance not in valid_responses :
144
+ continue
145
+
146
+ donation = donations [participant ]
147
+ political_accounts = insta_data .load_political_account_list ()
148
+ parties = ['SP' , 'SVP' , 'Mitte' , 'FDP' ]
149
+ p_follows_party = {p : False for p in parties }
150
+ for account in donation :
151
+ profile = account ['string_list_data' ][0 ]['href' ]
152
+ if profile in political_accounts .keys ():
153
+ insta_profile = political_accounts [profile ]
154
+ profile_type = insta_profile ['type' ]
155
+ if profile_type != 'party' :
156
+ continue
157
+ profile_party = insta_profile ['party' ]
158
+ if profile_party in parties :
159
+ p_follows_party [profile_party ] = True
160
+
161
+ # Add to result
162
+ for party , follows in p_follows_party .items ():
163
+ if follows :
164
+ self .party_counts [party ][pol_stance ] += 1
165
+ return
110
166
111
167
def update_sm_use (self , responses = None ):
112
168
var = 'media_use-4'
@@ -125,18 +181,28 @@ def get_decryptor(self, project):
125
181
return Decryption (settings .SECRET_KEY , project .get_salt ())
126
182
127
183
def get_responses (self ):
184
+ """
185
+ Returns dictionary with responses per participant.
186
+ {'participant_id': {'response-var': <response>, ...}}
187
+ """
128
188
project = self .get_project ()
129
189
reference_date = self .get_reference_date ()
130
190
131
191
responses = QuestionnaireResponse .objects .filter (
132
192
project = project , time_submitted__gte = reference_date )
133
193
134
194
decryptor = self .get_decryptor (project )
135
- decrypted_responses = [ResponseSerializer (r , decryptor = decryptor ).data ['responses' ] for r in responses ]
136
-
195
+ decrypted_responses = {}
196
+ for r in responses :
197
+ serialized_r = ResponseSerializer (r , decryptor = decryptor )
198
+ decrypted_responses [serialized_r .data ['participant' ]] = serialized_r .data ['responses' ]
137
199
return decrypted_responses
138
200
139
201
def get_blueprint_donations (self , bp_pk ):
202
+ """
203
+ Returns dictionary with donations per participant.
204
+ {'participant_id': <extracted donation>}
205
+ """
140
206
project = self .get_project ()
141
207
reference_date = self .get_reference_date ()
142
208
blueprint = DonationBlueprint .objects .get (pk = bp_pk )
@@ -145,6 +211,8 @@ def get_blueprint_donations(self, bp_pk):
145
211
blueprint = blueprint , time_submitted__gte = reference_date )
146
212
147
213
decryptor = self .get_decryptor (project )
148
- decrypted_donations = [DonationSerializer (d , decryptor = decryptor ).data ['data' ] for d in donations ]
149
-
214
+ decrypted_donations = {}
215
+ for d in donations :
216
+ serialized_d = DonationSerializer (d , decryptor = decryptor )
217
+ decrypted_donations [serialized_d .data ['participant' ]] = serialized_d .data ['data' ]
150
218
return decrypted_donations
0 commit comments