def comprehension(origin=None): lb, ub = fcast_app.correct_bins[0], fcast_app.correct_bins[-1] init_bins = list((np.array(fcast_app.correct_bins)-lb)/(ub-lb)) init_prob = [1./(len(init_bins)-1)] * (len(init_bins)-1) return Branch( *comprehension_check( instructions=Page( Label( ''' <p>Watch the full instructional video before continuing. </p> ''' + instructions_vid ), timer=('InstructionsTime', -1) ), checks=Page( gen_dashboard( src='/fcast-instr/', bins=init_bins, prob=init_prob, var='CompCheck', data_rows=-1, submit=S.verify_fcast() ), back=True ), attempts=3 ), navigate=N.fcast() )
def fcast(origin=None): questions = texts.fcast_questions.copy() n_bins_list = [choice(N_BINS) for q in questions] fcast_pages = [ Page( gen_dashboard( '/fcast/', label=label, n_bins=n_bins, var='Forecast', record_order=True ), timer='ForecastTime', embedded=[Embedded('Variable', var), Embedded('NBins', n_bins)] ) for (var, label), n_bins in zip(questions, n_bins_list) ] shuffle(fcast_pages) for i, page in enumerate(fcast_pages): page.questions.insert( 0, Label( '<p><b>Question {} of {}</b></p>'.format(i+1, len(fcast_pages)) ) ) return Branch( *fcast_pages, Page( Label(texts.completion), terminal=True ) )
def start(): assigner.next() return Branch(consent_page(''' By entering your MTurk ID, you consent to sell us your first-born son for no more than $102.23. '''), basic_demographics(page=True, require=True), navigate=rate_articles, navigate_worker=True)
def rate_articles(start_branch): def select_articles(part): if part.meta['Condition'] == 'random': return random.sample(ARTICLES, k=N_ARTICLES) df = pd.DataFrame(part.get_data()) df['Ideal'] = df['Condition'] == 'ideal' df = df.append((len(ARTICLES) - 1) * [df], ignore_index=True) df['ArticleName'] = ARTICLE_NAMES X = df[cols] y_pred = reg.predict(X) article_ratings = list(zip(ARTICLES, y_pred)) article_ratings.sort(key=lambda x: x[1], reverse=True) return [article for article, rating in article_ratings][:N_ARTICLES] # def gen_rate_articles_page(name, headline, url): # page = Page( # RangeInput( # ''' # <p>From 0 (not at all) to 10 (very much), how much do you think you'd enjoy reading the following article?</p> # <p><b>{}</b></p> # '''.format(headline), # min=0, max=10, required=True, var='Enjoy' # ) # ) # if start_branch.part.meta['Ideal']: # page.questions.insert( # 0, # Label( # ''' # First, think of the sort of news an ideal version of yourself would enjoy reading. # ''' # ) # ) # return page def gen_rate_articles_page(name, headline, url): return Page( RangeInput(''' <p>Take a few minutes to read <a href="{}" target="_blank">this article</a>.</p> {} <p>From 0 (not at all ) to 10 (very much), how much did you enjoy reading that article?</p> '''.format(url, headline), min=0, max=10, required=True, var='Enjoy')) # articles = random.sample(ARTICLES, k=N_ARTICLES) articles = select_articles(start_branch.part) start_branch.embedded.append( Embedded('ArticleName', [name for name, headline, url in articles])) return Branch(*[gen_rate_articles_page(*article) for article in articles], navigate=end)
def start(): """ :return: branch with consent form and preliminary questions :rtype: hemlock.Branch """ return Branch(consent_page(open('texts/consent.md', 'r').read()), Page(attention_check()), basic_demographics(page=True), *crt('bat_ball', 'flowers', 'students', 'green_round', 'stock', 'whales', page=True), berlin(), navigate=first_estimates_branch)
def ultimatum_game(start_branch): def gen_check_page(accept): return Page(Label(), Input('How much money does the proposer receive?', prepend='$', append='.00', type='number', required=True), Input('How much money does the responder receive?', prepend='$', append='.00', type='number', required=True), compile=[C.clear_response(), C.random_proposal(accept)]) proposer = assigner.next()['Proposer'] return Branch( *comprehension_check( instructions=Page( Label( open('ug_instructions.md', 'r').read()\ .format(POT=POT, N_ROUNDS=N_ROUNDS) ) ), checks=[ gen_check_page(accept=True), Page( Label('Correct! One more check to pass.') ), gen_check_page(accept=False) ], attempts=3 ), Page( Label('You passed the comprehension check!') ), Page( Label( f"You are about to play an ultimatum game as a **{'proposer' if proposer else 'responder'}**." ) ), navigate=proposer_branch if proposer else responder_branch )
def start(): return Branch( Page( Label(texts.consent_label), Check( choices=[('I consent to participate', 'consent')], validate=V.correct_choices( 'consent', error_msg='<p>Please consent to participate.</p>' ) ) ), demographics( 'age_bins', 'gender', 'race', 'education', page=True, require=True ), *crt(page=True, require=True), berlin(require=True), navigate=N.comprehension() )
def proposer_branch(ug_branch): branch = Branch(navigate=end) for i in range(N_ROUNDS): branch.pages += [ Page( Label(progress(i / N_ROUNDS, f'Round {i+1} of {N_ROUNDS}')), proposal_input := Blank((f''' You have ${POT} to split between you and the responder. Fill in the blank: I would like to offer the responder **$''', '.00**.'), prepend='$', append='.00', var='Proposal', blank_empty='__', type='number', min=0, max=POT, required=True)), Page(Label(compile=C.display_proposer_outcome(proposal_input))) ] return branch
def start(): return Branch( *comprehension_check( instructions=Page( Label('Here are some instructions') ), checks=Page( Check( '<p>Select the correct choice.</p>', ['Correct', 'Incorrect', 'Also incorrect'], compile=[C.clear_response(), C.shuffle()], validate=V.require(), submit=S.correct_choices('Correct') ) ), attempts=3 ), Page( Label('You passed the comprehension check!'), terminal=True ) )
def responder_branch(ug_branch): branch = Branch(navigate=end) for i in range(N_ROUNDS): branch.pages += [ Page( Label(progress(i / N_ROUNDS, f'Round {i+1} of {N_ROUNDS}')), response_input := Blank((f''' The proposer has ${POT} to split between him/herself and you. Fill in the blank: I will accept any proposal which gives me at least **$''', '.00**.'), prepend='$', append='.00', var='Response', blank_empty='__', type='number', min=0, max=POT, required=True)), Page(Label(compile=C.display_responder_outcome(response_input))) ] return branch
def first_estimates_branch(start_branch=None): """ :param start_branch: :type start_branch: hemlock.Branch :return: branch with first estimate questions :rtype: hemlock.Branch """ def make_first_estimate_questions(): """ :return: first estimate questions :rtype: list of hemlock.Blank """ fcast_keys = fcast_selector.next() fcast_keys = (list(fcast_keys) if isinstance(fcast_keys, tuple) else [fcast_keys]) shuffle(fcast_keys) current_user.embedded.append(Embedded('Forecast', fcast_keys)) return [(key, make_fcast_questions(key, context, first_estimate=True)) for key in fcast_keys] assigner.next() context = use_context(first_estimate=True) first_estimate_questions = make_first_estimate_questions() return Branch( Page(Label(INSTRUCTIONS['first'][current_user.meta['Context']])), *[ Page(Label(progress(i / N_FCASTS, f'Estimate {i+1} of {N_FCASTS}')), Dashboard(src='/dashapp/', g={ 'fcast_key': key, 'context': context }), *questions, timer='FirstEstimateTime') for i, (key, questions) in enumerate(first_estimate_questions) ], navigate=N.second_estimates_branch(first_estimate_questions))
def start(): return Branch(berlin(), Page(Label(compile=display_score), terminal=True))
def end(rate_articles_branch): return Branch(completion_page())
def second_estimates_branch(first_estimate_branch, first_estimate_questions): """Create branch for second estimates :param first_estimate_branch: branch for first estimates :type first_estimate_branch: hemlock.Branch :param first_estimate_questions: questions containing participant's first estimates :type first_estimate_questions: list of (time-series key, question) tuples :return: second estimates branch :rtype: hemlock.Branch """ def make_instructions_labels(): """ :return: instructions labels for second estimates :rtype: list of hemlock.Label """ labels = [Label(open('texts/second_estimate.md', 'r').read())] if current_user.meta['Context'] == 'second-only': labels.append(Label(open('texts/second_estimate_addcontext.md'))) return labels def make_second_estimate_page(i, key, questions): """ :param i: estimate number :type i: int :param key: name of time-series :type key: str :param questions: corresponding first estimate questions :type questions: list of hemlock.Blank :return: page asking for second estimates :rtype: hemlock.Page """ labels = make_fcast_question_labels(key, context) return Page( Label(progress(i / N_FCASTS, f'Estimate {i+1} of {N_FCASTS}')), Dashboard(src='/dashapp/', g={ 'fcast_key': key, 'context': context }), Label(f''' Your first estimates were: {make_list( [ label[0]+q.response+label[1] for label, q in zip(labels, questions) ] )} '''), # additional questions (i.e., for dialectical bootstrapping) *make_additional_questions(), # estimation questions *make_fcast_questions(key, context, first_estimate=False), timer='SecondEstimateTime') def make_additional_questions(): """Make additional questions, such as prompts for dialectical bootstrapping :return: additional questions :rtype: list of hemlock.Question """ if not current_user.meta['Bootstrap']: return [ Label(''' Please make second estimates which are different from your first estimates. ''') ] return [ Textarea(''' Imagine your first estimates were off the mark. Write at least one reason why that could be. Which assumptions or considerations could have been wrong? ''', var='Assumptions', required=True, validate=V.min_words(7), debug=[ D.send_keys('here are 7 words without a meaning'), D.send_keys(p_exec=.2) ]), Check(''' What does this reason imply? Were your first estimates too high or too low? ''', [('Too high', 'high'), ('Too low', 'low'), ('Some were too high, others too low', 'both')], var='Direction', validate=V.require()), Label(''' Based on this new perspective, make second estimates which are different from your first estimates. ''') ] context = use_context(first_estimate=False) return Branch( Page(Label(INSTRUCTIONS['second'][current_user.meta['Context']])), *[ make_second_estimate_page(i, key, questions) for i, (key, questions) in enumerate(first_estimate_questions) ], Page(*[ likert( f'Compared to the average person, how much do you know about {forecast_questions[key]["know_about"]}?', [ 'Much less than average', 'Less than average', 'About average', 'More than average', 'Much more than average' ], var='ContextKnowledge') for key, _ in first_estimate_questions ]), Page( binary(''' Did you look up the answers to any of the questions we asked? It's important that you answer honestly for research purposes. Your answer won't affect your bonus. ''', var='LookUp', data_rows=-1, validate=V.require()), Textarea( 'Do you have any suggestions for how to improve our study? Feedback is greatly appreciated!', var='AdditionalComments', data_rows=-1)), completion_page())
def start(): return Branch( *crt('bat_ball', 'lily_pads', 'widgets', 'students', page=True), Page(Label(compile=display_score), terminal=True))
def start(): conditions = assigner.next() return Branch(Page(Label('Page ' + conditions['set0'])), Page(Label('Page ' + conditions['set1'])), Page(Label('The end!'), terminal=True))
def start(): return Branch(comprehensive_demographics(page=True), Page(Label('The end.'), terminal=True))
def end(rounds_branch): return Branch( Page(Label('Thank you for completing the survey!'), terminal=True))