import os from otree.api import Currency as c, currency_range from ._builtin import Page, WaitPage from .models import Constants import numpy as np import json from NewsSocialSignaling import TwitterProcessor import pickle import io import matplotlib matplotlib.use('Agg') from matplotlib import pyplot as plt import base64 import copy import datetime as dt import threading import time class Authentication(Page): form_model = 'player' live_method = 'live_handler' form_fields = ['verifier_code'] def error_message(self, values): print('Verifying') verifier_code = values['verifier_code'] print(verifier_code) resource = self.participant.vars['auth_resource'] access_token_list = self.player.twitter_get_oauth_token(verifier=verifier_code, ro_key=resource[0], ro_secret=resource[1]) user_data = self.player.twitter_get_access_token(access_token_list=access_token_list, name='baseline') # except Exception as e: # print(e) # return 'Error validating user: {0}'.format(e) self.participant.vars['twitter_user_baseline'] = user_data def vars_for_template(self): return { 'auth_url': self.player.auth_url() } # def before_next_page(self): class Authentication2(Page): form_model = 'player' live_method = 'live_handler' def vars_for_template(self): return { 'user_data': json.dumps(self.participant.vars['twitter_user'], indent=4) } def infographic_to_graphic(fig, sn): buffer = io.BytesIO() fig.savefig(buffer, format='png', dpi=300) static_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), '_static') fn = os.path.join(static_path, 'infographics', sn + '_peers' + '.png') if not os.path.exists(os.path.dirname(fn)): os.makedirs(os.path.dirname(fn)) fig.savefig(fn, format='png', dpi=300) buffer.seek(0) image_png = buffer.getvalue() buffer.close() graphic = base64.b64encode(image_png) graphic = graphic.decode('utf-8') return graphic class SummaryStatistic(Page): form_model = 'player' def vars(self): public_treatment = True if 'shown_summary_stat' in self.participant.vars and self.participant.vars['shown_summary_stat']: name = 'post_revisions' suffix = '_' + name user_name = 'user_data' + suffix if user_name not in self.participant.vars or (dt.datetime.utcnow() - self.participant.vars['user_added' + suffix]).total_seconds() / 60 > 5: access_token_list = self.participant.vars['auth_access_tokens'] self.player.twitter_get_access_token(access_token_list=access_token_list, name=name) retweet_page = True else: print('Vars Baseline') suffix = '_baseline' retweet_page = False user = { 'id': self.participant.vars['user_data' + suffix]['id'], 'screen_name': self.participant.vars['user_data' + suffix]['screen_name'], 'most_recent_followers': self.participant.vars['user_followers' + suffix], 'most_recent_friends': self.participant.vars['user_friends' + suffix], 'most_recent': self.participant.vars['user_data' + suffix] } print('Accounts following: {0}'.format(TwitterProcessor.accounts_following(user=user))) info = TwitterProcessor.build_infographic(user=user, savefig=False) fig = info['fig'] tweet_text = info['text'] self.participant.vars['user' + suffix] = user self.participant.vars['img_pickled' + suffix] = pickle.dumps(fig) graphic = infographic_to_graphic(fig=fig, sn=user['screen_name']) # format tweet_text for url tweet_text = tweet_text.replace('%', '%25').replace('@', '%40') tweet_text += '%0A%0AView your own news diet at INSERT OUR URL' # get summary of friends information (if in network treatment) peer_info = self.player.add_peer_info(user) self.participant.vars['eligible_for_public'] = False peer_treatment = False peer_graphic = None if isinstance(peer_info, dict) and len(peer_info['sampled_friends']) > 0: peer_treatment = True self.participant.vars['eligible_for_public'] = True info_peer = TwitterProcessor.build_infographic_peers(user=user, peer_data=peer_info, savefig=False) peer_graphic = infographic_to_graphic(fig=info_peer['fig'], sn=user['screen_name']) return { 'infographic': graphic, # 'slant_score': TwitterProcessor.calculate_user_slant(user=user), # 'hard_score': TwitterProcessor.calculate_user_hard(user=user), # 'instructions_text': instructions_text, 'retweet_page': retweet_page, 'public_treatment': public_treatment, 'infographic_path': '/static/infographics/{0}.png'.format(user['screen_name']), 'tweet_text': tweet_text, 'peer_treatment': peer_treatment, 'peer_infographic': peer_graphic } def vars_for_template(self): return self.vars() # def js_vars(self): # return self.vars() def before_next_page(self): self.participant.vars['shown_summary_stat'] = True @staticmethod def calc_summary_stat(user): hard_score = NewsSocialSignaling.TwitterProcessor.calculate_user_hardscore(user=user) slant_score = NewsSocialSignaling.TwitterProcessor.calculate_user_slant(user=user) # TODO: handle nulls return { 'hard': 100 * np.random.rand(), 'slant': 100 * np.random.rand(), # TODO: If 0, return something slightly higher to avoid overflow 'num_followers': user['most_recent'].followers_count } class Recommendations(Page): form_model = 'player' live_method = 'live_handler' def vars(self): n = 5 if 'recommendations' in self.participant.vars and len(self.participant.vars['recommendations']) > n: recs = self.participant.vars['recommendations'] else: user = self.participant.vars['user_baseline'] possible_suggestions = TwitterProcessor.publisher_suggestions(user=user) self.participant.vars['possible_possible_recommendations'] = copy.copy(possible_suggestions) # now sample suggestions (try and do equal positive and negative slant) recs = [] for sign in [-1, 1]: poss_recs = [el for el in possible_suggestions if np.sign(el['slant_change']) == sign] print(poss_recs) if len(poss_recs) > 0: recs += [el for el in np.random.choice(poss_recs, size=min(n, len(poss_recs)), replace=False)] np.random.shuffle(recs) for r in recs: total_width = 150 r['arrow_total_width'] = np.abs(total_width * r['slant_change']) + 30 r['arrow_line_width'] = np.abs(total_width * r['slant_change']) self.participant.vars['recommendations'] = recs return { 'recommendations': recs, } def vars_for_template(self): return self.vars() def js_vars(self): return self.vars() def before_next_page(self): pass page_sequence = [Authentication, SummaryStatistic, Recommendations, SummaryStatistic]