first commit
This commit is contained in:
commit
73fc2121bf
30 changed files with 13308 additions and 0 deletions
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
venv
|
||||
staticfiles
|
||||
./db.sqlite3
|
||||
.idea
|
||||
*~
|
||||
*.sqlite3
|
||||
_static_root
|
||||
_bots*s
|
||||
__temp*
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.DS_Store
|
||||
*.otreezip
|
||||
/Sample Code/
|
||||
42
Finish/Comments.html
Normal file
42
Finish/Comments.html
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ block title }}
|
||||
Comments
|
||||
{{ endblock }}
|
||||
{{ block styles}}
|
||||
|
||||
|
||||
{{ endblock }}
|
||||
{{ block scripts}}
|
||||
|
||||
|
||||
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
|
||||
<p>
|
||||
We would like to know more about your thought process when doing the task.
|
||||
Namely,
|
||||
<br>
|
||||
- How did you decide which option to choose?
|
||||
<br>
|
||||
- What was important in guessing how your opponent chose?
|
||||
<br>
|
||||
- How sure were you that you were choosing well?
|
||||
<br>
|
||||
<br>
|
||||
Any feedback you have will be useful for us.
|
||||
</p>
|
||||
|
||||
{{ formfields }}
|
||||
|
||||
<p>
|
||||
Click 'Next' to complete the task. You must do this to receive your payment.
|
||||
<br>
|
||||
<br>
|
||||
Thank you for participating.
|
||||
</p>
|
||||
|
||||
{{ next_button }}
|
||||
|
||||
{{ endblock }}
|
||||
31
Finish/Demographics.html
Normal file
31
Finish/Demographics.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ block title }}
|
||||
Questionnaire
|
||||
{{ endblock }}
|
||||
{{ block styles}}
|
||||
|
||||
|
||||
{{ endblock }}
|
||||
{{ block scripts}}
|
||||
|
||||
|
||||
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
|
||||
<p>
|
||||
Before we conclude, we would like to ask you a few questions about yourself.
|
||||
</p>
|
||||
|
||||
{{ formfields }}
|
||||
|
||||
<p>
|
||||
You must answer each question before you can continue.
|
||||
</p>
|
||||
|
||||
{{ next_button }}
|
||||
|
||||
|
||||
|
||||
{{ endblock }}
|
||||
34
Finish/EndOfExperiment.html
Normal file
34
Finish/EndOfExperiment.html
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
End of experiment
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
|
||||
{{ block styles }}
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
|
||||
{{ block scripts }}
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
|
||||
{{ block content }}
|
||||
|
||||
|
||||
<p>
|
||||
Thank you for participating.
|
||||
Click 'Next' to complete the experiment.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You need to complete the experiment to receive your payment.
|
||||
</p>
|
||||
|
||||
{{ next_button }}
|
||||
|
||||
{{ endblock }}
|
||||
22
Finish/RedirectProlific.html
Normal file
22
Finish/RedirectProlific.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
Results
|
||||
{{ endblock }}
|
||||
|
||||
{{block scripts}}
|
||||
<script>
|
||||
let completionlink = js_vars.completionlink;
|
||||
|
||||
window.onload = function(){
|
||||
window.location.href=completionlink;
|
||||
}
|
||||
</script>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
21
Finish/RedirectQualtrics.html
Normal file
21
Finish/RedirectQualtrics.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
Results
|
||||
{{ endblock }}
|
||||
|
||||
{{block scripts}}
|
||||
<script>
|
||||
let elfecompletionlink = js_vars.elfecompletionlink;
|
||||
|
||||
window.onload = function(){
|
||||
window.location.href=elfecompletionlink;
|
||||
}
|
||||
</script>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
139
Finish/__init__.py
Normal file
139
Finish/__init__.py
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
from otree.api import *
|
||||
import numpy as np
|
||||
import random
|
||||
import operator
|
||||
|
||||
|
||||
doc = """
|
||||
App to characterise complexity of decision-making, with sums with varying numbers of elements in each sum.
|
||||
"""
|
||||
|
||||
|
||||
class C(BaseConstants):
|
||||
NAME_IN_URL = 'end'
|
||||
PLAYERS_PER_GROUP = None
|
||||
NUM_ROUNDS = 1
|
||||
|
||||
|
||||
|
||||
class Subsession(BaseSubsession):
|
||||
pass
|
||||
|
||||
|
||||
class Group(BaseGroup):
|
||||
pass
|
||||
|
||||
|
||||
class Player(BasePlayer):
|
||||
participation_fee= models.CurrencyField()
|
||||
|
||||
# Standard survey questions
|
||||
Age = models.IntegerField(min=18, label="Please enter your age:")
|
||||
EducationLevel = models.StringField(
|
||||
label="What is the highest level of education that you <span style='font-weight:bold'>completed</span>?",
|
||||
choices=[
|
||||
"Primary Education or Less",
|
||||
"Secondary Education/High School",
|
||||
"Business, technical, or vocational school after Secondary Education/High School",
|
||||
"Some college or university qualification, but not a Bachelor",
|
||||
"Bachelor or equivalent",
|
||||
"Master or Post-graduate training or professional schooling after college (e.g., law or medical school)",
|
||||
"Ph.D. or equivalent"
|
||||
],
|
||||
widget = widgets.RadioSelect
|
||||
)
|
||||
EducationField = models.StringField(
|
||||
label="Choose the field that best describes your <span style='font-weight:bold'>primary field of education</span>.",
|
||||
choices=[
|
||||
"Generic",
|
||||
"Arts and Humanities",
|
||||
"Social Sciences and Journalism",
|
||||
"Economics",
|
||||
"Education",
|
||||
"Business, Administration, and Law",
|
||||
"Computer Science, Information, and Communication Technologies",
|
||||
"Natural Sciences",
|
||||
"Mathematics and Statistics",
|
||||
"Engineering, Manufacturing, and Construction",
|
||||
"Agriculture, Forestry, Fisheries, and Veterinary",
|
||||
"Health and Welfare",
|
||||
"Services (Transport, Hygiene and Health, Security, and Other)"
|
||||
],
|
||||
widget = widgets.RadioSelect
|
||||
)
|
||||
Comments = models.LongStringField(
|
||||
label="If you have any comments, please leave them below.",
|
||||
blank=True
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# PAGES
|
||||
class Demographics(Page):
|
||||
"""Socio-demographic questions"""
|
||||
form_model = 'player'
|
||||
form_fields = ['Age', 'EducationLevel', 'EducationField']
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return player.round_number == C.NUM_ROUNDS
|
||||
|
||||
|
||||
class Comments(Page):
|
||||
"""Comments"""
|
||||
form_model = 'player'
|
||||
form_fields = ['Comments']
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return player.round_number == C.NUM_ROUNDS
|
||||
|
||||
|
||||
class EndOfExperiment(Page):
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
return dict(
|
||||
context=player.session.config['context']
|
||||
)
|
||||
|
||||
class RedirectProlific(Page):
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
player.round_number == C.NUM_ROUNDS and
|
||||
player.session.config['context'] == "prolific" and
|
||||
not player.participant.vars.get('failed_captcha', False)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def js_vars(player):
|
||||
return dict(
|
||||
completionlink=
|
||||
player.subsession.session.config['completionlink']
|
||||
)
|
||||
|
||||
class RedirectQualtrics(Page):
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
player.round_number == C.NUM_ROUNDS and
|
||||
player.session.config['context'] == "lab" and
|
||||
not player.participant.vars.get('failed_captcha', False)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def js_vars(player):
|
||||
return dict(
|
||||
elfecompletionlink=
|
||||
player.session.config['elfecompletionlink']+"participantid="+player.participant.code+"&sessionid="+player.session.config['elfesessionid']
|
||||
)
|
||||
|
||||
page_sequence = [
|
||||
Demographics,
|
||||
Comments,
|
||||
EndOfExperiment,
|
||||
RedirectProlific,
|
||||
RedirectQualtrics
|
||||
]
|
||||
10
Finish/tests.py
Normal file
10
Finish/tests.py
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
from otree.api import Currency as c, currency_range, expect, Bot, SubmissionMustFail
|
||||
from . import *
|
||||
import random
|
||||
|
||||
|
||||
class PlayerBot(Bot):
|
||||
def play_round(self):
|
||||
if self.round_number == 1:
|
||||
yield Submission(EndOfExperiment, check_html = False)
|
||||
|
||||
2
Procfile
Normal file
2
Procfile
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
web: otree prodserver1of2
|
||||
worker: otree prodserver2of2
|
||||
185
Start/Welcome.html
Normal file
185
Start/Welcome.html
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
{{ block title }}
|
||||
Welcome!
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
<style>
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.popup {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
background-color: #fefefe;
|
||||
margin: 5% auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #888;
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.close {
|
||||
color: #aaaaaa;
|
||||
float: right;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: none;
|
||||
}
|
||||
.information_sheet_button {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
.information_sheet_button:hover {
|
||||
color: darkblue;
|
||||
}
|
||||
.information_sheet_button:active {
|
||||
color: darkblue;
|
||||
}
|
||||
.information_sheet_button:focus {
|
||||
color: darkblue;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<div>
|
||||
<p>Thank you for participating in this study.</p>
|
||||
<p>
|
||||
In this study, we will ask you to make choices.
|
||||
You will get {{session.config.currency_symbol}}{{participation_fee|to2}} when completing the study.
|
||||
<br>
|
||||
You can earn an additional bonus payment of up to {{session.config.currency_symbol}}{{max_payment|to2}}, depending on your choices.
|
||||
</p>
|
||||
<p>
|
||||
This study is conducted under a strict policy of no deception. You will never be lied to during this study.
|
||||
The instructions will detail how the study works and how you are paid.
|
||||
</p>
|
||||
{{ if use_captchas == 1 }}
|
||||
<h3>
|
||||
'Bot'-Detection
|
||||
</h3>
|
||||
<p>
|
||||
This study is designed for humans and cannot be fulfilled using automated answers. You will be asked to transcribe easily legible words in this study. If you fail to transcribe a word three times, the study will be immediately terminated and you will not be able to complete it nor receive payment.
|
||||
</p>
|
||||
</p>
|
||||
{{ endif }}
|
||||
</div>
|
||||
<div class="form-group required">
|
||||
<h2>Informed Consent</h2>
|
||||
<p>
|
||||
Your participation in this study is voluntary. You can withdraw consent or discontinue participation at any time.
|
||||
All data and published work resulting from this study will be anonymised and maintain your individual privacy.
|
||||
</p>
|
||||
<p>
|
||||
Please read this <span class="information_sheet_button">information sheet</span> to decide if you want to participate in this study.
|
||||
You need to open this document to proceed. Should you have any questions or concerns, please contact the researchers or the UCL Research Ethics Office.
|
||||
</p>
|
||||
|
||||
Participant's statement: I confirm that:
|
||||
<ol type="a">
|
||||
<li>I have read and understood the <span class="information_sheet_button">information sheet</span>; </li>
|
||||
<li>I understand that I can refuse or withdraw from this study at any time without affecting my rights or status; </li>
|
||||
<li>I am 18 or older and I freely consent to participate in this study; </li>
|
||||
<li>I may ask the researchers for a copy of these documents for my records.</li>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
Do you agree with the statement above and consent to participate in the study?<br>
|
||||
<label>
|
||||
<input type="radio" name="consent" value="Yes"> Yes, I agree and wish to participate in the study.
|
||||
</label><br>
|
||||
<label>
|
||||
<input type="radio" name="consent" value="No"> No, I do not agree and do not wish to participate in the study.
|
||||
</label><br>
|
||||
<span id="consent_error" style="color: #b94a48; visibility: hidden">Please indicate whether you agree to participate in the study.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="otree-form-errors alert alert-danger" id="no_consent_error" style="display: none">
|
||||
You have chosen not to participate in the study. Please close this page.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
Next, we will provide instructions explaining how the study works and how you will be paid.
|
||||
As a reminder, you will never be lied to during this or any study at the UCL Experimental Laboratory for Finance and Economics (UCL ELFE).
|
||||
</p>
|
||||
<p>When you are ready, please click "Next" to go on. </p>
|
||||
</div>
|
||||
|
||||
<div style="justify-content: center; align-items: center; text-align: center;">
|
||||
<button class="otree-btn-next btn btn-primary next-button otree-next-button" type="button" id="next_button" style="margin:auto;" onclick="checkConsent()">Next</button>
|
||||
</div>
|
||||
|
||||
<div class="popup" id="popup">
|
||||
<div class="popup-content">
|
||||
<span class="close">×</span>
|
||||
<iframe src="https://uclelfe.github.io/documents/UCL%20ELFE.%20Information%20Sheet.pdf#toolbar=0" width="100%" height="100%"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let popup = document.getElementById("popup");
|
||||
let information_sheet_button_1 = document.getElementsByClassName("information_sheet_button")[0];
|
||||
let information_sheet_button_2 = document.getElementsByClassName("information_sheet_button")[1];
|
||||
let close = document.getElementsByClassName("close")[0];
|
||||
|
||||
information_sheet_button_1.onclick = function() {
|
||||
popup.style.display = "block";
|
||||
}
|
||||
|
||||
information_sheet_button_2.onclick = function() {
|
||||
popup.style.display = "block";
|
||||
}
|
||||
|
||||
close.onclick = function() {
|
||||
popup.style.display = "none";
|
||||
}
|
||||
|
||||
window.onclick = function(event) {
|
||||
if (event.target === popup) {
|
||||
popup.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
function checkConsent() {
|
||||
let consent = document.querySelectorAll('input[name="consent"]');
|
||||
let consent_error = document.getElementById("consent_error");
|
||||
let no_consent_error = document.getElementById("no_consent_error");
|
||||
|
||||
if (consent[0].checked === false && consent[1].checked === false) {
|
||||
consent_error.style.visibility = "visible";
|
||||
consent_error.scrollIntoView();
|
||||
} else if (consent[1].checked === true) {
|
||||
no_consent_error.style.display = "block";
|
||||
no_consent_error.scrollIntoView();
|
||||
} else {
|
||||
document.getElementById("form").submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{{ endblock }}
|
||||
50
Start/__init__.py
Normal file
50
Start/__init__.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
from otree import session
|
||||
from otree.api import *
|
||||
|
||||
|
||||
doc = """
|
||||
Landing page with consent.
|
||||
"""
|
||||
|
||||
|
||||
class C(BaseConstants):
|
||||
NAME_IN_URL = 'Start'
|
||||
PLAYERS_PER_GROUP = None
|
||||
NUM_ROUNDS = 1
|
||||
|
||||
|
||||
class Subsession(BaseSubsession):
|
||||
pass
|
||||
|
||||
|
||||
class Group(BaseGroup):
|
||||
pass
|
||||
|
||||
|
||||
class Player(BasePlayer):
|
||||
consent = models.BooleanField(blank=True)
|
||||
exp = models.IntegerField()
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
# PAGES
|
||||
class Welcome(Page):
|
||||
form_model = 'player'
|
||||
form_fields = ['consent']
|
||||
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
return dict(
|
||||
participation_fee=float(player.session.config['participation_fee']),
|
||||
max_payment=float(player.session.config['max_payment']),
|
||||
use_captchas=player.session.config['use_captchas'],
|
||||
estimated_completion_time=player.session.config['estimated_completion_time'],
|
||||
# usinstructions = player.session.config['usinstructions'],
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def before_next_page(player: Player, timeout_happened):
|
||||
player.exp = 1
|
||||
player.participant.vars['exp'] = 1
|
||||
|
||||
page_sequence = [Welcome]
|
||||
88
Task1/Captcha.html
Normal file
88
Task1/Captcha.html
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
Bot Detection
|
||||
{{ endblock }}
|
||||
{{ block styles}}
|
||||
<style>
|
||||
#timer_display {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
position: fixed;
|
||||
bottom: 1rem;
|
||||
right: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{{ endblock }}
|
||||
{{ block scripts}}
|
||||
<script src="{{ static 'js/vue.js' }}"></script>
|
||||
<script src="{{ static 'js/lodash.min.js' }}"></script>
|
||||
<script>
|
||||
var vm = new Vue({
|
||||
el: '#main_container',
|
||||
delimiters: ['${', '}'],
|
||||
data: {
|
||||
attempt: {{ attempt }},
|
||||
time_now: null,
|
||||
start_time: null,
|
||||
end_time: null,
|
||||
time_limit: {{ max_captcha_time }},
|
||||
time_until_end: {{ max_captcha_time }},
|
||||
},
|
||||
computed: {
|
||||
time_until_end_display: function () {
|
||||
s = _.clone(this.time_until_end)
|
||||
if (s>=60) {return (s-(s%=60))/60+(9<s?':':':0')+s}
|
||||
else if (s>=0) {return s}
|
||||
else {return '0'}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.start_time = _.now()/1000
|
||||
this.end_time = this.start_time + this.time_limit
|
||||
|
||||
window.setInterval(() => {
|
||||
this.time_now = _.now()/1000;
|
||||
this.time_until_end = (this.end_time - this.time_now).toFixed(0);
|
||||
if (this.time_until_end <= 0) {
|
||||
if (document.querySelectorAll("input[type=text]")[0].value == "") {
|
||||
document.querySelectorAll("input[type=text]")[0].value = "NULL TIMEOUT"
|
||||
}
|
||||
document.getElementById("submit_button").click();
|
||||
}
|
||||
}
|
||||
, 1000)
|
||||
},
|
||||
})
|
||||
</script>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
<div id="main_container" v-cloak>
|
||||
<br>
|
||||
<div id="captcha">
|
||||
<h3>Bot Detection - Attempt ${attempt}</h3>
|
||||
<p>
|
||||
Type the following word or phrase into the box below, then press 'Next'. Answers are not case-sensitive.
|
||||
<br>
|
||||
You have three attempts. If you fail all three attempts, the task will end and you will not be paid.
|
||||
<br>
|
||||
You have one minute per attempt.
|
||||
</p>
|
||||
<div id="captcha_image">
|
||||
<img src="{{ static image_path }}" style='width:300px;'/>
|
||||
</div>
|
||||
<br>
|
||||
{{ formfields }}
|
||||
<button class="btn btn-primary" id="submit_button">Next</button>
|
||||
</div>
|
||||
<div id="timer_display"><span>${time_until_end_display}</span></div>
|
||||
</div>
|
||||
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
|
||||
19
Task1/CaptchaFailed.html
Normal file
19
Task1/CaptchaFailed.html
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
Bot Detection Failed
|
||||
{{ endblock }}
|
||||
|
||||
{{ block styles}}
|
||||
{{ endblock }}
|
||||
|
||||
{{ block scripts}}
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
<p>
|
||||
You failed the transcription task three times. <br>
|
||||
You will not be able to continue the experiment.
|
||||
</p>
|
||||
{{ endblock }}
|
||||
195
Task1/Instructions.html
Normal file
195
Task1/Instructions.html
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block styles}}
|
||||
{{ endblock }}
|
||||
|
||||
{{ block title }}
|
||||
Instructions
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
<input name="time_spent_instructions" type="hidden" id="time_spent_instructions">
|
||||
{{ include "Task1/InstructionsBase.html" }}
|
||||
|
||||
<div id="main_container" v-cloak>
|
||||
<div id="questions_container">
|
||||
<h3>Questions</h3>
|
||||
<p>
|
||||
You must answer the following questions correctly before you can proceed.
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<question v-for="(question, question_index) in questions" :question="question" :question_index="question_index" v-on:update_response="question.r=$event">
|
||||
</question>
|
||||
</ol>
|
||||
<div id="check_answers">
|
||||
<button type="button" class="btn btn-primary" @click="check_answers">Check Answers</button>
|
||||
<br>
|
||||
<p v-if="incorrect_answer_numbers != null && incorrect_answer_numbers.length > 0">
|
||||
<!-- The following answers are incorrect: <span v-for="q in incorrect_answer_numbers.slice(0, -1)">${q}, </span><span>${incorrect_answer_numbers[incorrect_answer_numbers.length-1]}.</span>
|
||||
<br> -->
|
||||
Some of the questions are unanswered or incorrect.
|
||||
You must answer all questions correctly before you can proceed.
|
||||
<br>
|
||||
Update your answers and try again.
|
||||
</p>
|
||||
<p v-if="incorrect_answer_numbers != null && incorrect_answer_numbers.length == 0">
|
||||
All answers are correct! Click 'Next' to proceed.
|
||||
</p>
|
||||
<button type="button" @click="instructions_time" v-if="incorrect_answer_numbers != null && incorrect_answer_numbers.length == 0" class="btn btn-primary">Next</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" v-model="incorrect_answers_string" name="incorrect_instruction_answers">
|
||||
<input type="hidden" v-model="errors_quiz_count" name="errors_quiz">
|
||||
<input type="hidden" id="time_spent_instructions" name="time_spent_instructions">
|
||||
|
||||
</div>
|
||||
{{ endblock }}
|
||||
|
||||
|
||||
|
||||
{{ block scripts }}
|
||||
<script>
|
||||
let startTime,submitTime
|
||||
window.addEventListener('load', function() {
|
||||
startTime=Date.now()
|
||||
})
|
||||
</script>
|
||||
|
||||
<!-- <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script> -->
|
||||
|
||||
<!--Loads vue.js-->
|
||||
<script src="{{ static 'js/vue.js' }}"></script>
|
||||
|
||||
<!--Defines what a question looks like-->
|
||||
<script type="text/x-template" id="question-template">
|
||||
<li>
|
||||
<br>
|
||||
<label class="question_text"><span v-html="question.q"></span></label><br>
|
||||
<template v-for="answer in question.a">
|
||||
<input type="radio" :value="answer" v-model="response" @change="$emit('update_response', $event.target.value)">
|
||||
<label v-html="answer" class="question_text" :for="answer"></label>
|
||||
<br>
|
||||
</template>
|
||||
<br>
|
||||
</li>
|
||||
</script>
|
||||
|
||||
<script>
|
||||
Vue.component('question', {
|
||||
props: ['question','question_index'],
|
||||
template: '#question-template',
|
||||
name: 'question',
|
||||
delimiters: ['${', '}'],
|
||||
data: function () {
|
||||
return {
|
||||
response: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
update_response: function() {
|
||||
console.log(this.question_index,this.response)
|
||||
},
|
||||
}
|
||||
});
|
||||
var vm = new Vue({
|
||||
el: '#main_container',
|
||||
delimiters: ['${', '}'],
|
||||
data: {
|
||||
incorrect_answers: [], errors_quiz: 0,
|
||||
questions: [
|
||||
{
|
||||
'q': 'True or False? You and your opponent always have the same baseline points.',
|
||||
'a': [
|
||||
'True.',
|
||||
'False.',
|
||||
],
|
||||
'c': 'False.',
|
||||
'r': null
|
||||
},
|
||||
{
|
||||
'q': 'True or False? The asset is worth the same for you and your opponent.',
|
||||
'a': [
|
||||
'True.',
|
||||
'False.',
|
||||
],
|
||||
'c': 'True.',
|
||||
'r': null
|
||||
},
|
||||
{
|
||||
'q': 'True or False? If you choose Option A (the asset), you always get the points associated with the asset.',
|
||||
'a': [
|
||||
'True.',
|
||||
'False.'
|
||||
],
|
||||
'c': 'False.',
|
||||
'r': null
|
||||
},
|
||||
{
|
||||
'q': 'True or False? If you choose Option B (baseline points), you get the points only if your opponent also chooses Option B.',
|
||||
'a': [
|
||||
'True.',
|
||||
'False.'
|
||||
],
|
||||
'c': 'False.',
|
||||
'r': null
|
||||
},
|
||||
{
|
||||
'q': 'True or False? If you choose Option B (baseline points), you get the points only if your opponent also chooses Option B.',
|
||||
'a': [
|
||||
'True.',
|
||||
'False.'
|
||||
],
|
||||
'c': 'False.',
|
||||
'r': null
|
||||
},
|
||||
{
|
||||
'q': 'Choose the correct answer if you want to maximise the probability of winning the bonus payment of {{ session.config.currency_symbol }}{{ session.config.bonus | to2 }}.',
|
||||
'a': [
|
||||
'Your guess does not matter for earning the bonus.',
|
||||
'It is always better to make the best guess possible.'
|
||||
],
|
||||
'c': 'It is always better to make the best guess possible.',
|
||||
'r': null
|
||||
}
|
||||
]
|
||||
},
|
||||
computed: {
|
||||
incorrect_answer_numbers: function() {
|
||||
ia = this.incorrect_answers
|
||||
if (ia.length === 0) {return null}
|
||||
else {return ia[ia.length-1].map((a) => a[0])}
|
||||
},
|
||||
incorrect_answers_string: function() {
|
||||
return JSON.stringify(this.incorrect_answers)
|
||||
},
|
||||
errors_quiz_count: function(){
|
||||
return this.errors_quiz-1
|
||||
},
|
||||
questions: function() {
|
||||
questions = this.common_questions
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
check_answers: function() {
|
||||
incorrect_answers = [];
|
||||
this.questions.forEach((q,i) => {if (q.c !== q.r) {incorrect_answers.push([i+1,q.r])}})
|
||||
this.incorrect_answers.push(incorrect_answers)
|
||||
this.errors_quiz = this.errors_quiz + 1
|
||||
},
|
||||
instructions_time: function(){
|
||||
submitTime = Date.now()
|
||||
if (document.getElementById("time_spent_instructions").value) {
|
||||
document.getElementById("time_spent_instructions").value
|
||||
}
|
||||
else {
|
||||
document.getElementById("time_spent_instructions").value = submitTime - startTime;
|
||||
}
|
||||
document.getElementById("form").submit();
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{{ endblock }}
|
||||
94
Task1/InstructionsBase.html
Normal file
94
Task1/InstructionsBase.html
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<h3>
|
||||
Your Task
|
||||
</h3>
|
||||
<p>
|
||||
This task has {{ C.NUM_PAYMENT_ROUNDS }} rounds.
|
||||
<br>
|
||||
Every round, you and other participants (1) make a choice and (2) guess the choices of other participants.
|
||||
Your choice and guess will determine how likely you are to get a bonus of {{ player.session.config.currency_symbol }}{{ player.session.config.bonus | to2 }}.
|
||||
<br>
|
||||
At the end of the task, you will be paid the participation fee of {{ player.session.config.currency_symbol }}{{ player.session.config.participation_payment | to2 }} and one round will be chosen randomly to determine your chance of getting the bonus.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In each round, you will be randomly matched with another participant (your opponent). Both you and your opponent must choose between an asset (Option A) and the assigned baseline points (Option B).
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Option A:</strong> You receive the asset's value if your opponent chooses Option B. If both you and your opponent choose Option A, both of you receive 0 points.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Option B:</strong> You receive your assigned baseline points, regardless of what your opponent chooses.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Key Details</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Asset's Value:</strong> The asset is worth the same amount of points for both you and your opponent.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Baseline Points:</strong> At the start of each round, every participant is assigned a random number of baseline points between 0 and 100. All values are equally likely and have been randomised for each participant.<br>
|
||||
<strong>You will not know your opponent's baseline points and your opponent will not know your baseline points.</strong>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Same Incentives for Everyone:</strong> Everyone else in the task follows these same rules and has the same incentives as you.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Independence:</strong> The asset value, your baseline points, and your opponent's baseline points vary each round. Your choices across rounds are independent and do not affect one another.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Example</h3>
|
||||
<p>
|
||||
Suppose the asset (Option A) is worth 50 points and your baseline points (Option B) are 38.4.
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
If you choose Option B, you are guaranteed to receive your baseline points of 38.4.
|
||||
</li>
|
||||
<li>
|
||||
If you choose Option A and your opponent chooses Option B, you receive the asset value of 50.
|
||||
</li>
|
||||
<li>
|
||||
If both you and your opponent choose Option A, both of you receive 0 points.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Guesses</h3>
|
||||
<p>
|
||||
In addition, we will ask you what you believe other participants will do.
|
||||
The more accurate your guess is, the more likely you are to get the bonus.
|
||||
</p>
|
||||
|
||||
<h3>Bonus Payment Rule</h3>
|
||||
<p>
|
||||
Your choice and guess will determine how likely you are to get the bonus.
|
||||
The payment rule is designed so that
|
||||
(1) you choose to maximise what your points given how likely you think others are to invest or not;
|
||||
(2) you tell us what you believe the probability is that your opponent chooses each action.
|
||||
<br>
|
||||
To ensure this, your payment from guesses is determined as follows:
|
||||
<ul>
|
||||
<li>At the end of the study, one round will be randomly selected, and either your choice or your guess is chosen to determine payment, both equally likely.</li>
|
||||
<li>If your choice is selected for payment, then the probability you get the bonus equals the number of points you got from your choice, as described above.</li>
|
||||
<li>If your guess is selected for payment, we draw two random choices according to your guess.
|
||||
You get 50 points for each choice that matches the choice of your opponent.
|
||||
In addition, you get 50 points if the two drawn choices are different.
|
||||
The probability you get the bonus equals the resulting total number of points.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<h3>Practice Rounds</h3>
|
||||
<p>
|
||||
In order to get familiarised with the task, you will begin with {{ C.NUM_PRACTICE_ROUNDS }} practice rounds.
|
||||
The practice rounds do not count toward your chance of getting the bonus.
|
||||
<br>
|
||||
There is also a brief questionnaire at the end.
|
||||
</p>
|
||||
|
||||
<!-- Treatments:
|
||||
Baseline
|
||||
N samples with replacement, forced and free
|
||||
Sample as many times as they want
|
||||
-->
|
||||
19
Task1/NewRound.html
Normal file
19
Task1/NewRound.html
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
{{ block title }}
|
||||
Main Task
|
||||
{{ endblock }}
|
||||
{{ block content }}
|
||||
<div>
|
||||
<p>
|
||||
You will now make choices {{ C.NUM_PAYMENT_ROUNDS }} rounds.<br>
|
||||
One of these rounds will be randomly selected to <b>determine your bonus payment</b> at the end of the task. <br>
|
||||
You will not receive feedback.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div style="justify-content: center; align-items: center; text-align: center;">
|
||||
{{ next_button }}
|
||||
</div>
|
||||
|
||||
{{ endblock }}
|
||||
185
Task1/Task.html
Normal file
185
Task1/Task.html
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
{{ if player.practice == 1 }}
|
||||
Practice Round {{ practice_round_number }} out of {{ C.NUM_PRACTICE_ROUNDS }}
|
||||
{{ endif }}
|
||||
{{ if player.practice == 0 }}
|
||||
Round {{ payment_round_number }} out of {{ C.NUM_PAYMENT_ROUNDS }}
|
||||
{{ endif }}
|
||||
{{ endblock }}
|
||||
|
||||
{{ block scripts }}
|
||||
<script>
|
||||
// (A) PREVENT CONTEXT MENU FROM OPENING
|
||||
window.addEventListener("contextmenu", evt => evt.preventDefault(), false);
|
||||
// (B) PREVENT CLIPBOARD COPYING
|
||||
window.addEventListener("copy", evt => {
|
||||
evt.clipboardData.setData("text/plain", "Copying is not allowed on this page");
|
||||
evt.preventDefault();
|
||||
}, false);
|
||||
|
||||
window.addEventListener("load", (event) => {
|
||||
let startTime,submitTime
|
||||
startTime=Date.now()
|
||||
document.getElementById("instructions_clicked").value = 0
|
||||
const div = document.querySelectorAll('div')
|
||||
div.forEach(function(x){
|
||||
if (x.classList.contains('otree-form-errors')){
|
||||
x.innerHTML="Please make your choice and guess."
|
||||
}
|
||||
})
|
||||
|
||||
// SLIDER
|
||||
const slider = document.getElementById('belief_slider');
|
||||
const leftSpan = document.getElementById('left-value');
|
||||
const rightSpan = document.getElementById('right-value');
|
||||
const hidden = document.getElementById('id_belief_1');
|
||||
const sliderContainer = document.getElementById('slider-container');
|
||||
|
||||
if (slider) {
|
||||
slider.addEventListener('input', function() {
|
||||
// Show the thumb on first move
|
||||
sliderContainer.classList.remove('empty-slider');
|
||||
sliderContainer.classList.add('interacted');
|
||||
|
||||
// Update text and hidden input
|
||||
let val = parseFloat(this.value);
|
||||
leftSpan.innerText = val.toFixed(1);
|
||||
rightSpan.innerText = (100 - val).toFixed(1);
|
||||
hidden.value = val.toFixed(1);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById("ok_button").addEventListener('click', function () {
|
||||
submitTime = Date.now()
|
||||
if (document.getElementById("time_spent").value) {
|
||||
document.getElementById("time_spent").value
|
||||
} else {
|
||||
document.getElementById("time_spent").value = submitTime - startTime;
|
||||
}
|
||||
document.getElementById("form").submit();
|
||||
})
|
||||
});
|
||||
|
||||
function show_Instructions() {
|
||||
document.getElementById("instructions_clicked").value = 1
|
||||
let elem1 = document.getElementById("instructions_button"), text1 = elem1.innerText;
|
||||
if (text1 === "Show Instructions"){
|
||||
elem1.innerHTML = "Hide Instructions";}
|
||||
else{
|
||||
elem1.innerHTML = "Show Instructions";
|
||||
}
|
||||
let x1 = document.getElementById("Instructions");
|
||||
if (x1.style.display === "none") {
|
||||
x1.style.display = "block";
|
||||
}
|
||||
else {
|
||||
x1.style.display = "none";
|
||||
}
|
||||
};
|
||||
|
||||
// Delay choices
|
||||
setTimeout(function () {
|
||||
document.getElementById("interface").style.visibility = "visible";
|
||||
document.getElementById("ok_button").style.visibility = "visible";
|
||||
document.getElementById("instructions_button").style.visibility = "visible";
|
||||
}, 2000);
|
||||
</script>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block styles }}
|
||||
<style>
|
||||
/* Slider No-Value Start */
|
||||
.empty-slider input[type=range]::-webkit-slider-thumb { visibility: hidden; }
|
||||
.empty-slider input[type=range]::-moz-range-thumb { visibility: hidden; }
|
||||
.interacted input[type=range]::-webkit-slider-thumb { visibility: visible; }
|
||||
.interacted input[type=range]::-moz-range-thumb { visibility: visible; }
|
||||
.form-range { width: 100%; cursor: pointer; }
|
||||
</style>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
<input name="instructions_clicked" type="hidden" id="instructions_clicked">
|
||||
<input name="time_spent" type="hidden" id="time_spent">
|
||||
|
||||
<br>
|
||||
<div class="container">
|
||||
<div class="center">
|
||||
<p>
|
||||
Asset's worth: {{ player.value | to0 }} points.
|
||||
<br>
|
||||
Your baseline points: {{ player.cost | to1 }}.
|
||||
<br>
|
||||
Opponent's baseline points: a random number between 0 and 100, all equally likely.
|
||||
<br>
|
||||
You will not know your opponent's baseline points and your opponent will not know your baseline points.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
|
||||
<div id="interface" style="visibility: hidden;">
|
||||
<p>Which option do you choose?</p>
|
||||
<table id="alternatives" class="center">
|
||||
<tr>
|
||||
<td style="width:10%">
|
||||
<input class="form-check-input" type="radio" id="id_choice-0" name="decision" required="" value="0">
|
||||
</td>
|
||||
<td>Option A: Asset's worth if opponent chooses Option B.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%">
|
||||
<input class="form-check-input" type="radio" id="id_choice-1" name="decision" required="" value="1">
|
||||
</td>
|
||||
<td>Option B: Baseline points.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br><br>
|
||||
|
||||
<p>
|
||||
What do you think is the probability that your opponent chooses each option:
|
||||
</p>
|
||||
<div class="center" style="max-width: 600px; margin: 40px auto; margin-top: 0px;">
|
||||
<!-- <p>Please select a value by clicking on the bar below:</p> -->
|
||||
<div id="slider-container" class="empty-slider">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
|
||||
<div style="width:80px; text-align:left;">
|
||||
Option A <br>
|
||||
<span id="left-value">--</span>%
|
||||
<!-- <br>Asset<br> -->
|
||||
</div>
|
||||
<div style="flex:1;">
|
||||
<input type="range" class="form-range" id="belief_slider" min="0" max="100" step="0.1" value="50">
|
||||
</div>
|
||||
<div style="width:80px; text-align:right;">
|
||||
Option B <br>
|
||||
<span id="right-value">--</span>%
|
||||
<!-- <br>Opponent's <br> Baseline Points -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="belief_1" id="id_belief_1" value="">
|
||||
</div>
|
||||
|
||||
{{ if player.practice == 1 }}
|
||||
<div class="container"><div class="centering"><button type="button" class="btn btn-primary" style="visibility: hidden;" id="ok_button">Receive feedback</button></div></div>
|
||||
{{ endif }}
|
||||
{{ if player.practice == 0 }}
|
||||
<div class="container"><div class="centering"><button type="button" class="btn btn-primary" style="visibility: hidden;" id="ok_button">Next</button></div></div>
|
||||
{{ endif }}
|
||||
|
||||
<div class="container">
|
||||
<div class="centering">
|
||||
<button type="button" style="visibility: hidden;" class="btn btn-secondary" id="instructions_button" onclick="show_Instructions()">Show Instructions</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="Instructions" style="display: none" class="card bg-light instructions">
|
||||
<div class="card-body">
|
||||
{{ include "Task1/InstructionsBase.html"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ endblock }}
|
||||
225
Task1/TaskFeedback.html
Normal file
225
Task1/TaskFeedback.html
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block title }}
|
||||
{{ if player.practice == 1 }}
|
||||
Practice Round {{ practice_round_number }} out of {{ C.NUM_PRACTICE_ROUNDS }}
|
||||
{{ endif }}
|
||||
{{ if player.practice == 0 }}
|
||||
Round {{ payment_round_number }} out of {{ C.NUM_PAYMENT_ROUNDS }}
|
||||
{{ endif }}
|
||||
{{ endblock }}
|
||||
|
||||
{{ block scripts }}
|
||||
<script>
|
||||
// (A) PREVENT CONTEXT MENU FROM OPENING
|
||||
window.addEventListener("contextmenu", evt => evt.preventDefault(), false);
|
||||
// (B) PREVENT CLIPBOARD COPYING
|
||||
window.addEventListener("copy", evt => {
|
||||
evt.clipboardData.setData("text/plain", "Copying is not allowed on this page");
|
||||
evt.preventDefault();
|
||||
}, false);
|
||||
|
||||
window.addEventListener("load", (event) => {
|
||||
let startTime,submitTime
|
||||
startTime=Date.now()
|
||||
document.getElementById("instructions_clicked").value = 0
|
||||
const div = document.querySelectorAll('div')
|
||||
div.forEach(function(x){
|
||||
if (x.classList.contains('otree-form-errors')){
|
||||
x.innerHTML="Please make your choice and guess."
|
||||
}
|
||||
})
|
||||
|
||||
// SLIDER
|
||||
const slider = document.getElementById('belief_slider');
|
||||
const leftSpan = document.getElementById('left-value');
|
||||
const rightSpan = document.getElementById('right-value');
|
||||
const hidden = document.getElementById('id_belief_1');
|
||||
const sliderContainer = document.getElementById('slider-container');
|
||||
|
||||
if (slider) {
|
||||
slider.addEventListener('input', function() {
|
||||
// Show the thumb on first move
|
||||
sliderContainer.classList.remove('empty-slider');
|
||||
sliderContainer.classList.add('interacted');
|
||||
|
||||
// Update text and hidden input
|
||||
let val = parseFloat(this.value);
|
||||
leftSpan.innerText = val.toFixed(1);
|
||||
rightSpan.innerText = (100 - val).toFixed(1);
|
||||
hidden.value = val.toFixed(1);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById("ok_button").addEventListener('click', function () {
|
||||
submitTime = Date.now()
|
||||
if (document.getElementById("time_spent").value) {
|
||||
document.getElementById("time_spent").value
|
||||
} else {
|
||||
document.getElementById("time_spent").value = submitTime - startTime;
|
||||
}
|
||||
document.getElementById("form").submit();
|
||||
})
|
||||
});
|
||||
|
||||
function show_Instructions() {
|
||||
document.getElementById("instructions_clicked").value = 1
|
||||
let elem1 = document.getElementById("instructions_button"), text1 = elem1.innerText;
|
||||
if (text1 === "Show Instructions"){
|
||||
elem1.innerHTML = "Hide Instructions";}
|
||||
else{
|
||||
elem1.innerHTML = "Show Instructions";
|
||||
}
|
||||
let x1 = document.getElementById("Instructions");
|
||||
if (x1.style.display === "none") {
|
||||
x1.style.display = "block";
|
||||
}
|
||||
else {
|
||||
x1.style.display = "none";
|
||||
}
|
||||
};
|
||||
|
||||
// Delay choices
|
||||
setTimeout(function () {
|
||||
document.getElementById("interface").style.visibility = "visible";
|
||||
document.getElementById("ok_button").style.visibility = "visible";
|
||||
document.getElementById("instructions_button").style.visibility = "visible";
|
||||
}, 0);
|
||||
|
||||
// Feedback
|
||||
document.getElementById("id_choice-0").disabled = true;
|
||||
document.getElementById("id_choice-1").disabled = true;
|
||||
|
||||
document.getElementById("belief_slider").disabled = true;
|
||||
document.getElementById("belief_slider").value = js_vars.belief_1;
|
||||
document.getElementById("left-value").innerText = parseFloat(js_vars.belief_1).toFixed(1);
|
||||
document.getElementById("right-value").innerText = (100 - parseFloat(js_vars.belief_1)).toFixed(1);
|
||||
|
||||
|
||||
if (js_vars.decision == 0){
|
||||
document.getElementById("id_choice-0").checked = true;
|
||||
}
|
||||
if (js_vars.decision == 1){
|
||||
document.getElementById("id_choice-1").checked = true;
|
||||
}
|
||||
|
||||
</script>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block styles }}
|
||||
<style>
|
||||
/* Slider No-Value Start */
|
||||
.empty-slider input[type=range]::-webkit-slider-thumb { visibility: hidden; }
|
||||
.empty-slider input[type=range]::-moz-range-thumb { visibility: hidden; }
|
||||
.interacted input[type=range]::-webkit-slider-thumb { visibility: visible; }
|
||||
.interacted input[type=range]::-moz-range-thumb { visibility: visible; }
|
||||
.form-range { width: 100%; cursor: pointer; }
|
||||
</style>
|
||||
{{ endblock }}
|
||||
|
||||
{{ block content }}
|
||||
<input name="instructions_clicked" type="hidden" id="instructions_clicked">
|
||||
<input name="time_spent" type="hidden" id="time_spent">
|
||||
|
||||
<br>
|
||||
<div class="container">
|
||||
<div class="center">
|
||||
<p>
|
||||
Asset's worth: {{ player.value | to0 }} points.
|
||||
<br>
|
||||
Your baseline points: {{ player.cost | to1 }}.
|
||||
<br>
|
||||
Opponent's baseline points: a random number between 0 and 100, all equally likely.
|
||||
<br>
|
||||
You will not know your opponent's baseline points and your opponent will not know your baseline points.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<br><br><br>
|
||||
|
||||
<div id="interface" style="visibility: hidden;">
|
||||
<p>Which option do you choose?</p>
|
||||
<table id="alternatives" class="center">
|
||||
<tr>
|
||||
<td style="width:10%">
|
||||
<input class="form-check-input" type="radio" id="id_choice-0" name="decision" required="" value="0">
|
||||
</td>
|
||||
<td>Option A: Asset's worth if opponent chooses Option B.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:10%">
|
||||
<input class="form-check-input" type="radio" id="id_choice-1" name="decision" required="" value="1">
|
||||
</td>
|
||||
<td>Option B: Baseline points.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br><br>
|
||||
|
||||
<p>
|
||||
What do you think is the probability that your opponent chooses each option:
|
||||
</p>
|
||||
<div class="center" style="max-width: 600px; margin: 40px auto; margin-top: 0px;">
|
||||
<!-- <p>Please select a value by clicking on the bar below:</p> -->
|
||||
<div id="slider-container" class="interacted">
|
||||
<div style="display:flex; align-items:center; justify-content:space-between; gap:12px;">
|
||||
<div style="width:80px; text-align:left;">
|
||||
Option A <br>
|
||||
<span id="left-value">--</span>%
|
||||
<!-- <br>Asset<br> -->
|
||||
</div>
|
||||
<div style="flex:1;">
|
||||
<input type="range" class="form-range" id="belief_slider" min="0" max="100" step="0.1" value="50">
|
||||
</div>
|
||||
<div style="width:80px; text-align:right;">
|
||||
Option B <br>
|
||||
<span id="right-value">--</span>%
|
||||
<!-- <br>Opponent's <br> Baseline Points -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="belief_1" id="id_belief_1" value="">
|
||||
</div>
|
||||
|
||||
|
||||
<div class="feedback-text">
|
||||
<p>
|
||||
In this practice round, you chose Option {{ if player.decision == 0 }}A{{ endif }}{{ if player.decision == 1}}B{{ endif }} and guessed that your opponent chose Option A with {{ belief_A | to1 }}% probability and Option B with {{ belief_B | to1 }}% probability.
|
||||
</p>
|
||||
<p>
|
||||
Recall that only one round is selected for payment and, in that round, only either your choice or your guess counts toward your payment.
|
||||
</p>
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
If your choice in this round were chosen for payment, you would get the {{ player.session.config.currency_symbol }}{{ player.session.config.bonus | to2 }} bonus with {{ if player.decision == 0 }}0% if your opponent chose Option A and {{ player.value | to0 }}% probability if your opponent chose Option B{{ endif }}{{ if player.decision == 1 }}{{ player.cost | to1 }}% probability, regardless of your opponent's choice{{ endif }}.
|
||||
</li>
|
||||
<li>
|
||||
If your guess in this round were chosen for payment, you would get the {{ player.session.config.currency_symbol }}{{ player.session.config.bonus | to2 }} bonus with {{ paymentbelief_A | to1 }}% if your opponent chose Option A and {{ paymentbelief_B | to1 }}% if your opponent chose Option B.
|
||||
</li>
|
||||
</ul>
|
||||
It is always best to submit your best guess to maximise the probability of getting paid the bonus.
|
||||
</p>
|
||||
<br>
|
||||
<p>
|
||||
Click 'Next' to see your instructions for this study.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{ if player.practice == 1 }}
|
||||
<div class="container"><div class="centering"><button type="button" class="btn btn-primary" style="visibility: hidden;" id="ok_button">Next</button></div></div>
|
||||
{{ endif }}
|
||||
|
||||
<div class="container">
|
||||
<div class="centering">
|
||||
<button type="button" style="visibility: hidden;" class="btn btn-secondary" id="instructions_button" onclick="show_Instructions()">Show Instructions</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="Instructions" style="display: none" class="card bg-light instructions">
|
||||
<div class="card-body">
|
||||
{{ include "Task1/InstructionsBase.html"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ endblock }}
|
||||
30
Task1/TaskIntro.html
Normal file
30
Task1/TaskIntro.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{{ extends "_static/global/Page.html" }}
|
||||
{{ load otree static }}
|
||||
{{ block title }}
|
||||
Main Task
|
||||
{{ endblock }}
|
||||
{{ block content }}
|
||||
<div>
|
||||
{{ if player.practice == 1}}
|
||||
<p>
|
||||
You will now have {{C.NUM_PRACTICE_ROUNDS}} practice round{{ if C.NUM_PRACTICE_ROUNDS > 1 }}s{{ endif }} to familiarise yourself with the study.
|
||||
<br>
|
||||
You will receive feedback after your choices.
|
||||
<br>
|
||||
You will not be paid for {{ if C.NUM_PRACTICE_ROUNDS == 1 }}this round{{ endif }}{{ if C.NUM_PRACTICE_ROUNDS > 1 }}these rounds{{ endif }}.
|
||||
</p>
|
||||
{{ endif }}
|
||||
{{ if player.practice == 0}}
|
||||
<p>
|
||||
You will now make choices {{ C.NUM_PAYMENT_ROUNDS }} rounds.<br>
|
||||
One of these rounds will be randomly selected to <b>determine your bonus payment</b> at the end of the task. <br>
|
||||
You will not receive feedback.
|
||||
</p>
|
||||
{{ endif }}
|
||||
</div>
|
||||
|
||||
<div style="justify-content: center; align-items: center; text-align: center;">
|
||||
{{ next_button }}
|
||||
</div>
|
||||
|
||||
{{ endblock }}
|
||||
313
Task1/__init__.py
Normal file
313
Task1/__init__.py
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
from otree.api import *
|
||||
import random
|
||||
import math
|
||||
import json
|
||||
import numpy as np
|
||||
import random
|
||||
import itertools
|
||||
|
||||
|
||||
doc = """Template"""
|
||||
|
||||
class C(BaseConstants):
|
||||
NAME_IN_URL = 'Decision'
|
||||
PLAYERS_PER_GROUP = None
|
||||
|
||||
# Rounds
|
||||
NUM_PRACTICE_ROUNDS = 2
|
||||
NUM_PAYMENT_ROUNDS = 3
|
||||
NUM_ROUNDS = NUM_PRACTICE_ROUNDS + NUM_PAYMENT_ROUNDS
|
||||
|
||||
# Captchas
|
||||
max_captcha_time = 60
|
||||
captcha_rounds = [1, 2, ] # The rounds in which captchas occur
|
||||
captcha_text = ["bonus", "payment", ] # The text the participants need to input (can use upper or lowercase)
|
||||
|
||||
treatments_between_list = [0, 1]
|
||||
cost_list = [5, 15, 25, 35, 45, 55, 65, 75, 85, 95]
|
||||
value_list = [10, 30, 50, 70, 90]
|
||||
payoffs_list = []
|
||||
for cost in cost_list:
|
||||
for value in value_list:
|
||||
payoffs_list.append([value, cost])
|
||||
|
||||
|
||||
|
||||
|
||||
class Subsession(BaseSubsession):
|
||||
pass
|
||||
|
||||
|
||||
class Group(BaseGroup):
|
||||
pass
|
||||
|
||||
|
||||
class Player(BasePlayer):
|
||||
practice = models.IntegerField()
|
||||
player_round = models.IntegerField()
|
||||
|
||||
decision = models.IntegerField()
|
||||
belief_1 = models.FloatField(min=0, max=100)
|
||||
|
||||
# Between-Participant Treatment
|
||||
treatment_between = models.IntegerField()
|
||||
|
||||
# Within-Participant Treatment
|
||||
treatment_index_within = models.IntegerField()
|
||||
value = models.FloatField()
|
||||
cost = models.FloatField()
|
||||
|
||||
# Time fields
|
||||
time_spent = models.IntegerField()
|
||||
time_spent_instructions = models.IntegerField()
|
||||
|
||||
# Captcha
|
||||
captcha_attempt_1 = models.StringField(label="", initial="")
|
||||
captcha_attempt_2 = models.StringField(label="", initial="")
|
||||
captcha_attempt_3 = models.StringField(label="", initial="")
|
||||
|
||||
# Instructions
|
||||
incorrect_instruction_answers = models.StringField(blank=True)
|
||||
errors_quiz = models.IntegerField()
|
||||
|
||||
instructions_clicked = models.BooleanField()
|
||||
|
||||
prolific_id = models.StringField(default=str(" "))
|
||||
|
||||
|
||||
|
||||
# FUNCTIONS
|
||||
def creating_session(subsession: Subsession):
|
||||
# Between-participant treatment
|
||||
# Extend between treatment list * Total participants in session /2 /Nr Between treatments and shuffle
|
||||
total_number_participants = 10 # max([1,math.floor(len(player.session.get_participants())/2/len(C.treatments_between_list))])
|
||||
between_treatment_list_shuffled = C.treatments_between_list * total_number_participants
|
||||
random.shuffle(between_treatment_list_shuffled)
|
||||
|
||||
# Within-participant treatment
|
||||
reps = len(C.payoffs_list) // C.NUM_PAYMENT_ROUNDS
|
||||
remainder = len(C.payoffs_list) % C.NUM_PAYMENT_ROUNDS
|
||||
|
||||
for player in subsession.get_players():
|
||||
|
||||
player.prolific_id = player.participant.label
|
||||
player.player_round = player.round_number
|
||||
|
||||
player.participant.vars['failed_captcha'] = False
|
||||
|
||||
# Between-participant treatment assignment
|
||||
player.treatment_between = between_treatment_list_shuffled[len(between_treatment_list_shuffled) % player.participant.id_in_session-1]
|
||||
|
||||
if player.round_number == 1:
|
||||
# Within-participant treatment assignment
|
||||
treatments_indices_within = list(range(len(C.payoffs_list))) * reps
|
||||
remaining_treatments = list(range(len(C.payoffs_list)))
|
||||
random.shuffle(remaining_treatments)
|
||||
treatments_indices_within = treatments_indices_within + remaining_treatments[:remainder]
|
||||
random.shuffle(treatments_indices_within)
|
||||
for r in range(C.NUM_PAYMENT_ROUNDS):
|
||||
player.in_round(C.NUM_PRACTICE_ROUNDS+1+r).treatment_index_within = treatments_indices_within[r]
|
||||
|
||||
if player.player_round <= C.NUM_PRACTICE_ROUNDS:
|
||||
player.practice = 1
|
||||
player.value = random.choice(C.value_list)
|
||||
player.cost = np.round(random.choice(C.cost_list)+10*(random.random()-.5),1)
|
||||
if player.player_round > C.NUM_PRACTICE_ROUNDS:
|
||||
player.practice = 0
|
||||
player.value = C.payoffs_list[player.treatment_index_within][0]
|
||||
player.cost = np.round(C.payoffs_list[player.treatment_index_within][1]+10*(random.random()-.5),1)
|
||||
|
||||
|
||||
|
||||
# PAGES
|
||||
class Instructions(Page):
|
||||
form_model = 'player'
|
||||
form_fields = ['incorrect_instruction_answers', 'errors_quiz', 'time_spent_instructions',]
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return player.round_number == 1
|
||||
|
||||
@staticmethod
|
||||
def vars_for_template(player: Player):
|
||||
return dict(
|
||||
participation_fee=player.session.config['participation_fee'],
|
||||
min_bonus_payment=player.session.config['min_bonus_payment'],
|
||||
max_bonus_payment=player.session.config['max_bonus_payment'],
|
||||
min_payment=player.session.config['min_payment'],
|
||||
max_payment=player.session.config['max_payment'],
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def before_next_page(player, timeout_happened):
|
||||
player.incorrect_instruction_answers = player.field_maybe_none('incorrect_instruction_answers')
|
||||
|
||||
|
||||
class TaskIntro(Page):
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
player.round_number in [1,C.NUM_PRACTICE_ROUNDS+1] and
|
||||
not player.participant.vars.get('failed_captcha', False)
|
||||
)
|
||||
|
||||
|
||||
class Task(Page):
|
||||
form_model = 'player'
|
||||
form_fields = ['decision','belief_1','time_spent',]
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
not player.participant.vars.get('failed_captcha', False)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
return dict(
|
||||
payment_round_number = player.round_number-C.NUM_PRACTICE_ROUNDS,
|
||||
practice_round_number = player.round_number,
|
||||
round_number = player.round_number,
|
||||
)
|
||||
|
||||
class TaskFeedback(Page):
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
player.round_number <= C.NUM_PRACTICE_ROUNDS and
|
||||
not player.participant.vars.get('failed_captcha', False)
|
||||
)
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
return dict(
|
||||
payment_round_number = player.round_number-C.NUM_PRACTICE_ROUNDS,
|
||||
practice_round_number = player.round_number,
|
||||
round_number = player.round_number,
|
||||
belief_A = player.belief_1,
|
||||
belief_B = 100-player.belief_1,
|
||||
paymentbelief_A = 2*player.belief_1-player.belief_1**2/100,
|
||||
paymentbelief_B = 100-player.belief_1**2/100,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def js_vars(player):
|
||||
return dict(
|
||||
decision = player.decision,
|
||||
belief_1 = player.belief_1,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CaptchaFailed(Page):
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
player.participant.vars.get('failed_captcha', True)
|
||||
)
|
||||
|
||||
class Captcha1(Page):
|
||||
template_name = 'Task1/Captcha.html'
|
||||
form_model = 'player'
|
||||
form_fields = ['captcha_attempt_1']
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
if not (
|
||||
player.round_number in C.captcha_rounds
|
||||
and not player.participant.vars.get('failed_captcha', False)
|
||||
and player.subsession.session.config['use_captchas'] == 1
|
||||
):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
max_captcha_time = C.max_captcha_time
|
||||
return {
|
||||
'image_path': "images/captchas/captcha{}.png".format(C.captcha_rounds.index(player.round_number) + 1),
|
||||
'attempt': 1,
|
||||
'max_captcha_time': max_captcha_time,
|
||||
}
|
||||
|
||||
|
||||
class Captcha2(Page):
|
||||
template_name = 'Task1/Captcha.html'
|
||||
form_model = 'player'
|
||||
form_fields = ['captcha_attempt_2']
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
if not (
|
||||
player.round_number in C.captcha_rounds
|
||||
and not player.participant.vars.get('failed_captcha', False)
|
||||
and player.subsession.session.config['use_captchas'] == 1
|
||||
):
|
||||
return False
|
||||
else:
|
||||
return player.captcha_attempt_1.lower() != C.captcha_text[C.captcha_rounds.index(player.round_number)].lower()
|
||||
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
max_captcha_time = C.max_captcha_time
|
||||
return {
|
||||
'image_path': "images/captchas/captcha{}.png".format(C.captcha_rounds.index(player.round_number) + 1),
|
||||
'attempt': 2,
|
||||
'max_captcha_time': max_captcha_time,
|
||||
}
|
||||
|
||||
|
||||
class Captcha3(Page):
|
||||
template_name = 'Task1/Captcha.html'
|
||||
form_model = 'player'
|
||||
form_fields = ['captcha_attempt_3']
|
||||
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
if not (
|
||||
player.round_number in C.captcha_rounds
|
||||
and not player.participant.vars.get('failed_captcha', False)
|
||||
and player.subsession.session.config['use_captchas'] == 1
|
||||
):
|
||||
return False
|
||||
else:
|
||||
return (
|
||||
player.captcha_attempt_1.lower() != C.captcha_text[
|
||||
C.captcha_rounds.index(player.round_number)
|
||||
].lower()
|
||||
and player.captcha_attempt_2.lower() != C.captcha_text[
|
||||
C.captcha_rounds.index(player.round_number)
|
||||
].lower()
|
||||
)
|
||||
@staticmethod
|
||||
def vars_for_template(player):
|
||||
max_captcha_time = C.max_captcha_time
|
||||
return {
|
||||
'image_path': "images/captchas/captcha{}.png".format(C.captcha_rounds.index(player.round_number) + 1),
|
||||
'attempt': 3,
|
||||
'max_captcha_time': max_captcha_time,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def before_next_page(player, timeout_happened):
|
||||
correct_text = C.captcha_text[C.captcha_rounds.index(player.round_number)].lower()
|
||||
if (
|
||||
player.round_number in C.captcha_rounds
|
||||
and player.captcha_attempt_1.lower() != correct_text
|
||||
and player.captcha_attempt_2.lower() != correct_text
|
||||
and player.captcha_attempt_3.lower() != correct_text
|
||||
):
|
||||
player.participant.vars['failed_captcha'] = True
|
||||
|
||||
|
||||
# Update page_sequence
|
||||
page_sequence = [
|
||||
Instructions,
|
||||
Captcha1,
|
||||
Captcha2,
|
||||
Captcha3,
|
||||
CaptchaFailed,
|
||||
TaskIntro,
|
||||
Task,
|
||||
TaskFeedback,
|
||||
]
|
||||
384
Tutorial oTree.md
Normal file
384
Tutorial oTree.md
Normal file
|
|
@ -0,0 +1,384 @@
|
|||
# Lecture: Introduction to oTree
|
||||
|
||||
**Goal:** Understand the architecture of an oTree application and build a basic Bayesian game.
|
||||
|
||||
---
|
||||
|
||||
### 0. Preliminaries:
|
||||
|
||||
- [Learn Python in X Minutes](https://learnxinyminutes.com/python/)
|
||||
- [oTree documentation](https://otree.readthedocs.io/en/latest/)
|
||||
- [oTree Tutorials](https://www.youtube.com/playlist?list=PLBL9eqPcwzGPli11Yighw5LWwzIifEFd_)
|
||||
- [Deploying oTree on Heroku via command line](https://www.youtube.com/watch?v=VrPdBEghYEM)
|
||||
|
||||
---
|
||||
## 1. oTree
|
||||
|
||||
### What is oTree?
|
||||
|
||||
oTree is an open-source, Starlette-based framework for implementing interactive experiments in the browser.
|
||||
|
||||
* **Logic:** Written in **Python**.
|
||||
* **Interface:** Written in **HTML/Starlette** template tags.
|
||||
* **Data Storage:** Automatic integration with **PostgreSQL** or **SQLite**.
|
||||
* **Deployment:** Easy to host on **Heroku** or local servers.
|
||||
|
||||
---
|
||||
|
||||
### Installation + project creation
|
||||
|
||||
#### Install
|
||||
```bash
|
||||
python -m pip install otree
|
||||
otree --version
|
||||
```
|
||||
|
||||
#### Create a project
|
||||
```bash
|
||||
otree startproject myproject
|
||||
cd myproject
|
||||
otree devserver
|
||||
```
|
||||
|
||||
Then open: `http://localhost:8000/`
|
||||
|
||||
#### Create an app inside the project
|
||||
```bash
|
||||
otree startapp my_app
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### File layout (important ones)
|
||||
|
||||
Inside the project:
|
||||
- `settings.py` — session configs, installed apps, currency settings, etc.
|
||||
- `_static/` — CSS/JS (optional)
|
||||
- `_templates/` — global templates (optional)
|
||||
- `my_app/` — your app code
|
||||
|
||||
Inside an app:
|
||||
- `__init__.py` — main app logic (models + pages + constants)
|
||||
- `templates/my_app/*.html` — participant-facing pages
|
||||
- `tests.py` — automated tests/bots (optional but recommended)
|
||||
|
||||
---
|
||||
|
||||
|
||||
### The Core Structure
|
||||
|
||||
An oTree project is organised into **Apps**. Each app contains:
|
||||
|
||||
* **`__init__.py`**: The "brain." Defines your models, variables, and logic.
|
||||
* **`Pages.py`**: Controls the sequence of what the participant sees.
|
||||
* **Templates (`.html`)**: The visual interface for each page.
|
||||
|
||||
|
||||
### The Hierarchy
|
||||
|
||||
1. **Session:** The entire group of participants.
|
||||
2. **Subsession:** A specific round within an app.
|
||||
3. **Group:** A collection of players interacting (e.g., in a prisoner's dilemma; we won't do this today).
|
||||
4. **Player:** The individual unit.
|
||||
5. **Pages**: The screens participants see (forms, instructions, results).
|
||||
|
||||
Data live in the database. Each **Player** has fields that get saved automatically.
|
||||
|
||||
---
|
||||
|
||||
### Defining Variables
|
||||
|
||||
Variables are defined in `__init__.py` under three classes: `Constants`, `Subsession`, `Group`, and `Player`.
|
||||
|
||||
```python
|
||||
class Constants(BaseConstants):
|
||||
NAME_IN_URL = 'Decision'
|
||||
PLAYERS_PER_GROUP = None
|
||||
NUM_PRACTICE_ROUNDS = 2
|
||||
NUM_PAYMENT_ROUNDS = 3
|
||||
NUM_ROUNDS = NUM_PRACTICE_ROUNDS + NUM_PAYMENT_ROUNDS
|
||||
|
||||
class Player(BasePlayer):
|
||||
decision = models.IntegerField()
|
||||
belief_1 = models.FloatField(min=0, max=100)
|
||||
captcha_attempt_1 = models.StringField(label="", initial="")
|
||||
|
||||
```
|
||||
|
||||
More types of fields here https://otree.readthedocs.io/en/latest/models.html#fields.
|
||||
|
||||
|
||||
### Forms and validation
|
||||
|
||||
Basic:
|
||||
```python
|
||||
class Decision(Page):
|
||||
form_model = "player"
|
||||
form_fields = ["choice"]
|
||||
```
|
||||
|
||||
Cross-field validation:
|
||||
```python
|
||||
class Player(BasePlayer):
|
||||
a = models.IntegerField()
|
||||
b = models.IntegerField()
|
||||
|
||||
class SomePage(Page):
|
||||
form_model = "player"
|
||||
form_fields = ["a", "b"]
|
||||
|
||||
@staticmethod
|
||||
def error_message(player, values):
|
||||
if values["a"] + values["b"] != 10:
|
||||
return "a + b must equal 10."
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
### Where to put logic: common hooks
|
||||
|
||||
- `Subsession.creating_session()`
|
||||
Initialise per-session/per-round variables, assign treatments, form groups.
|
||||
|
||||
- `Page.is_displayed(player)`
|
||||
Conditional page display (by round/treatment/role).
|
||||
|
||||
- `Page.vars_for_template(player)`
|
||||
Pass computed values to the template.
|
||||
|
||||
- `Page.error_message(player, values)`
|
||||
Validate across multiple fields.
|
||||
|
||||
- `Page.before_next_page(player, timeout_happened)`
|
||||
Compute payoffs, set state, write vars.
|
||||
|
||||
- `Group.set_payoffs()` (your own method)
|
||||
Common pattern: compute payoffs after everyone submits.
|
||||
|
||||
---
|
||||
|
||||
### Game Logic & Functions
|
||||
|
||||
Logic is triggered by events.
|
||||
|
||||
#### Determining if page is displayed
|
||||
|
||||
```python
|
||||
class TaskFeedback(Page):
|
||||
@staticmethod
|
||||
def is_displayed(player):
|
||||
return (
|
||||
player.round_number <= C.NUM_PRACTICE_ROUNDS and
|
||||
not player.participant.vars.get('failed_captcha', False)
|
||||
)
|
||||
```
|
||||
|
||||
#### Setting values in particular rounds
|
||||
|
||||
```python
|
||||
def creating_session(subsession: Subsession):
|
||||
for player in subsession.get_players():
|
||||
if player.round_number == 1:
|
||||
treatments_index = list(range(len(C.payoffs_list)))
|
||||
random.shuffle(treatments_index)
|
||||
for r in range(C.NUM_PAYMENT_ROUNDS):
|
||||
player.in_round(C.NUM_PRACTICE_ROUNDS+1+r).treatment_index = treatments_index[r]
|
||||
|
||||
```
|
||||
|
||||
Useful built-in methods: https://otree.readthedocs.io/en/latest/models.html#built-in-fields-and-methods.
|
||||
|
||||
---
|
||||
|
||||
### The User Interface
|
||||
|
||||
Templates use HTML combined with oTree tags to display data dynamically.
|
||||
|
||||
**Contribute.html**
|
||||
|
||||
```html
|
||||
{{ block title }}
|
||||
Round {{ payment_round_number }} out of {{ C.NUM_PAYMENT_ROUNDS }}
|
||||
{{ endblock }}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Live pages (real-time interaction)
|
||||
|
||||
For truly interactive real-time tasks (e.g., chat, continuous-time trading),
|
||||
oTree supports **live pages** (WebSocket-style). Basic pattern:
|
||||
|
||||
```python
|
||||
class MyLivePage(Page):
|
||||
live_method = "live_handler"
|
||||
|
||||
@staticmethod
|
||||
def live_handler(player, data):
|
||||
# data is a dict sent from JS
|
||||
return {player.id_in_group: dict(message="received")}
|
||||
```
|
||||
|
||||
You also write JS in the template to send/receive messages.
|
||||
|
||||
See more here: https://otree.readthedocs.io/en/latest/multiplayer/intro.html.
|
||||
|
||||
---
|
||||
|
||||
### Running the Server
|
||||
|
||||
To see your work in the browser:
|
||||
|
||||
1. **Initialise:** `otree devserver 8000`
|
||||
2. **Access:** Open `http://localhost:8000`
|
||||
3. **Data:** Go to the Admin tab to monitor real-time results and export CSV/Excel files.
|
||||
|
||||
---
|
||||
|
||||
### Quick Reference Table
|
||||
|
||||
| Command | Purpose |
|
||||
| --- | --- |
|
||||
| `otree startproject <name>` | Create a new project folder |
|
||||
| `otree startapp <name>` | Create a new app within the project |
|
||||
| `otree devserver` | Run the local testing server |
|
||||
| `otree zip` | Package the app for server upload |
|
||||
|
||||
---
|
||||
|
||||
|
||||
> **Important:** Always test your app using to ensure your payoff logic works before bringing in real participants.
|
||||
|
||||
---
|
||||
|
||||
## 2. Deployment
|
||||
|
||||
For testing/class projects, focus first on:
|
||||
- local devserver (`otree devserver`);
|
||||
- exporting data reliably.
|
||||
|
||||
Common option:
|
||||
1. oTree app on GitHub.
|
||||
2. Host on [heroku.com](heroku.com).
|
||||
3. Recruit on [UCL ELFE](https://uclelfe.github.io) or [Prolific.com](https://www.prolific.com).
|
||||
|
||||
Template already fitted to deal with this pipeline.
|
||||
The setting (in config; available when creating a session) completionlink is where you should put the prolific link.
|
||||
Prolific ID should be saved in participant labels.
|
||||
|
||||
---
|
||||
|
||||
### On Heroku
|
||||
- Create new app
|
||||
- Deploy from GitHub; manual deploy; then turn on automatic deployments
|
||||
- Add web dyno (GitHub education gives free dynos); worker dyno not needed
|
||||
- Add-on: postgresql (cheapest for testing)
|
||||
|
||||
Running for real:
|
||||
- Performance M dynos with auto-scalling with max latency of 500ms
|
||||
- Postgresql Standard 2
|
||||
- Config vars: OTREE_AUTH_LEVEL: STUDY; OTREE_PRODUCTION: 1; OTREE_ADMIN_PASSWORD: whateveryouwant
|
||||
|
||||
Downgrading postgresql is a real pain. Here's my cheatsheet:
|
||||
```bash
|
||||
Procedure to copy and remove previous database on heroku
|
||||
# Step 0. Login
|
||||
heroku login
|
||||
|
||||
# Step 1. Provision a new database
|
||||
heroku addons:create heroku-postgresql:essential-0 --app example-app
|
||||
|
||||
# Step 2. Enter maintenance mode to prevent database writes
|
||||
heroku maintenance:on --app appname
|
||||
|
||||
# Step 3. Transfer data to the new database
|
||||
## Check name and colour; or on website; it takes a while to provision, give it 2-3 minutes for new database to to show up
|
||||
heroku addons --all
|
||||
heroku config --app example-app
|
||||
## Copy
|
||||
heroku pg:copy app_name_to_copy_from::HEROKU_POSTGRESQL_COLOUR_TO_COPY_FROM HEROKU_POSTGRESQL_COLOUR_TO_COPY_TO --app app_name_to_copy_to
|
||||
|
||||
# Step 4. Promote the new database
|
||||
heroku pg:promote HEROKU_POSTGRESQL_COLOUR_TO_PROMOTE -a appname
|
||||
|
||||
# Step 5. Destroy previous database
|
||||
heroku addons:destroy HEROKU_POSTGRESQL_COLOUR --confirm appname
|
||||
|
||||
# Step 6. Exit maintenance mode
|
||||
heroku maintenance:off --app appname
|
||||
|
||||
|
||||
Example
|
||||
|
||||
heroku login
|
||||
heroku maintenance:on --app southern-path-2
|
||||
heroku addons:create heroku-postgresql:essential-0 --app southern-path-2
|
||||
heroku addons --all
|
||||
# This gets you the colours of the database; note that it takes a bit to provision, so they won't show immediately
|
||||
heroku config --app southern-path-2
|
||||
heroku pg:copy southern-path-2::DATABASE HEROKU_POSTGRESQL_PINK_URL --app southern-path-2 --confirm southern-path-2
|
||||
heroku pg:promote postgresql-clear-38905 -a southern-path-2
|
||||
heroku addons:destroy postgresql-round-22954 --confirm southern-path-2
|
||||
heroku maintenance:off --app southern-path-2
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### On Prolific
|
||||
|
||||
My typical study name: Survey on Decision-Making (up to **£X.00/Nmin** with bonus)
|
||||
|
||||
Internal name: Acronym YYYY.MM.DD
|
||||
|
||||
My typical description:
|
||||
```
|
||||
This survey seeks to understand how individuals make choices and is conducted by academic researchers.
|
||||
|
||||
You can earn up to £X.00 for Nmin.
|
||||
|
||||
You will earn a minimum of £Y.00.
|
||||
|
||||
Please keep in mind that how much you will receive will depend on your own choices and the choices of other participants. The payment scheme is designed to encourage you to think carefully about your choices.
|
||||
```
|
||||
|
||||
|
||||
- Study label: None
|
||||
- Device requirements: Desktop only
|
||||
- Labels: None
|
||||
- Limit participant access: Depends on your budget
|
||||
- What's the URL of your study?
|
||||
https://HEROKUAPPNAME.herokuapp.com/room/prolific?participant_label={{%PROLIFIC_PID%}}&STUDY_ID={{%STUDY_ID%}}&SESSION_ID={{%SESSION_ID%}}
|
||||
- How do you want to record IDs? URL parameters
|
||||
- Completion paths: Manually review
|
||||
- Screeners:
|
||||
- Current Country of Residence: United Kingdom (better sample)
|
||||
- Approval Rate: 95–100
|
||||
- Fluent languages: English
|
||||
- Exclude participants from other studies: any pilot and other waves of the same study that you've ran
|
||||
- Do participants require a login & password to access your survey tool? No
|
||||
- Total times a participant can complete your study: once
|
||||
- Reject exceptionally fast submissions: NO!
|
||||
|
||||
---
|
||||
|
||||
### On ELFE
|
||||
|
||||
- Login to main terminal.
|
||||
- Run the app in production mode, create ELFE session.
|
||||
- Turn on all terminals and open the link.
|
||||
- Test the Qualtrics questionnaire at the end.
|
||||
- Test (elfe.lab.run)[elfe.lab.run].
|
||||
- Schedule session on (elfe.lab.run)[elfe.lab.run] and invite participants.
|
||||
|
||||
On the day
|
||||
- Login to main terminal.
|
||||
- Run the app in production mode, create ELFE session.
|
||||
- Turn on all terminals and open the link.
|
||||
- Sit participants and allocate them on the app.
|
||||
- Let them start after all seated.
|
||||
- Take note of anything unusual.
|
||||
- Show timer and remind participants of the time every half hour or so.
|
||||
- Make sure everyone filled out the survey at the end before leaving (if they finished).
|
||||
- Pay participants (lab manager, via Wise account).
|
||||
9
_static/global/Page.html
Normal file
9
_static/global/Page.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{{ extends "otree/Page.html" }}
|
||||
{{ load otree static }}
|
||||
|
||||
{{ block global_styles }}
|
||||
<link rel="stylesheet" href="{% static 'global/custom.css' %}">
|
||||
{{ endblock }}
|
||||
|
||||
{{ block global_scripts }}
|
||||
{{ endblock }}
|
||||
25
_static/global/custom.css
Normal file
25
_static/global/custom.css
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
}
|
||||
.center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.otree-title {
|
||||
margin-top:-30px;
|
||||
}
|
||||
.container {
|
||||
height: 50px;
|
||||
position: relative;
|
||||
}
|
||||
.centering {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
BIN
_static/images/captchas/captcha1.png
Normal file
BIN
_static/images/captchas/captcha1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
_static/images/captchas/captcha2.png
Normal file
BIN
_static/images/captchas/captcha2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
136
_static/js/lodash.min.js
vendored
Normal file
136
_static/js/lodash.min.js
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* @license
|
||||
* Lodash lodash.com/license | Underscore.js 1.8.3 underscorejs.org/LICENSE
|
||||
*/
|
||||
;(function(){function n(n,t){return n.set(t[0],t[1]),n}function t(n,t){return n.add(t),n}function r(n,t,r){switch(r.length){case 0:return n.call(t);case 1:return n.call(t,r[0]);case 2:return n.call(t,r[0],r[1]);case 3:return n.call(t,r[0],r[1],r[2])}return n.apply(t,r)}function e(n,t,r,e){for(var u=-1,i=null==n?0:n.length;++u<i;){var o=n[u];t(e,o,r(o),n)}return e}function u(n,t){for(var r=-1,e=null==n?0:n.length;++r<e&&false!==t(n[r],r,n););return n}function i(n,t){for(var r=null==n?0:n.length;r--&&false!==t(n[r],r,n););
|
||||
return n}function o(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(!t(n[r],r,n))return false;return true}function f(n,t){for(var r=-1,e=null==n?0:n.length,u=0,i=[];++r<e;){var o=n[r];t(o,r,n)&&(i[u++]=o)}return i}function c(n,t){return!(null==n||!n.length)&&-1<d(n,t,0)}function a(n,t,r){for(var e=-1,u=null==n?0:n.length;++e<u;)if(r(t,n[e]))return true;return false}function l(n,t){for(var r=-1,e=null==n?0:n.length,u=Array(e);++r<e;)u[r]=t(n[r],r,n);return u}function s(n,t){for(var r=-1,e=t.length,u=n.length;++r<e;)n[u+r]=t[r];
|
||||
return n}function h(n,t,r,e){var u=-1,i=null==n?0:n.length;for(e&&i&&(r=n[++u]);++u<i;)r=t(r,n[u],u,n);return r}function p(n,t,r,e){var u=null==n?0:n.length;for(e&&u&&(r=n[--u]);u--;)r=t(r,n[u],u,n);return r}function _(n,t){for(var r=-1,e=null==n?0:n.length;++r<e;)if(t(n[r],r,n))return true;return false}function v(n,t,r){var e;return r(n,function(n,r,u){if(t(n,r,u))return e=r,false}),e}function g(n,t,r,e){var u=n.length;for(r+=e?1:-1;e?r--:++r<u;)if(t(n[r],r,n))return r;return-1}function d(n,t,r){if(t===t)n:{
|
||||
--r;for(var e=n.length;++r<e;)if(n[r]===t){n=r;break n}n=-1}else n=g(n,b,r);return n}function y(n,t,r,e){--r;for(var u=n.length;++r<u;)if(e(n[r],t))return r;return-1}function b(n){return n!==n}function x(n,t){var r=null==n?0:n.length;return r?k(n,t)/r:P}function j(n){return function(t){return null==t?F:t[n]}}function w(n){return function(t){return null==n?F:n[t]}}function m(n,t,r,e,u){return u(n,function(n,u,i){r=e?(e=false,n):t(r,n,u,i)}),r}function A(n,t){var r=n.length;for(n.sort(t);r--;)n[r]=n[r].c;
|
||||
return n}function k(n,t){for(var r,e=-1,u=n.length;++e<u;){var i=t(n[e]);i!==F&&(r=r===F?i:r+i)}return r}function E(n,t){for(var r=-1,e=Array(n);++r<n;)e[r]=t(r);return e}function O(n,t){return l(t,function(t){return[t,n[t]]})}function S(n){return function(t){return n(t)}}function I(n,t){return l(t,function(t){return n[t]})}function R(n,t){return n.has(t)}function z(n,t){for(var r=-1,e=n.length;++r<e&&-1<d(t,n[r],0););return r}function W(n,t){for(var r=n.length;r--&&-1<d(t,n[r],0););return r}function B(n){
|
||||
return"\\"+Tn[n]}function L(n){var t=-1,r=Array(n.size);return n.forEach(function(n,e){r[++t]=[e,n]}),r}function U(n,t){return function(r){return n(t(r))}}function C(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r];o!==t&&"__lodash_placeholder__"!==o||(n[r]="__lodash_placeholder__",i[u++]=r)}return i}function D(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=n}),r}function M(n){var t=-1,r=Array(n.size);return n.forEach(function(n){r[++t]=[n,n]}),r}function T(n){if(Bn.test(n)){
|
||||
for(var t=zn.lastIndex=0;zn.test(n);)++t;n=t}else n=tt(n);return n}function $(n){return Bn.test(n)?n.match(zn)||[]:n.split("")}var F,N=1/0,P=NaN,Z=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],q=/\b__p\+='';/g,V=/\b(__p\+=)''\+/g,K=/(__e\(.*?\)|\b__t\))\+'';/g,G=/&(?:amp|lt|gt|quot|#39);/g,H=/[&<>"']/g,J=RegExp(G.source),Y=RegExp(H.source),Q=/<%-([\s\S]+?)%>/g,X=/<%([\s\S]+?)%>/g,nn=/<%=([\s\S]+?)%>/g,tn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,rn=/^\w*$/,en=/^\./,un=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,on=/[\\^$.*+?()[\]{}|]/g,fn=RegExp(on.source),cn=/^\s+|\s+$/g,an=/^\s+/,ln=/\s+$/,sn=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,hn=/\{\n\/\* \[wrapped with (.+)\] \*/,pn=/,? & /,_n=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,vn=/\\(\\)?/g,gn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,dn=/\w*$/,yn=/^[-+]0x[0-9a-f]+$/i,bn=/^0b[01]+$/i,xn=/^\[object .+?Constructor\]$/,jn=/^0o[0-7]+$/i,wn=/^(?:0|[1-9]\d*)$/,mn=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,An=/($^)/,kn=/['\n\r\u2028\u2029\\]/g,En="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|\\ud83c[\\udffb-\\udfff])?)*",On="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+En,Sn="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]?|[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",In=RegExp("['\u2019]","g"),Rn=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff]","g"),zn=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+Sn+En,"g"),Wn=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)|\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)|\\d+",On].join("|"),"g"),Bn=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff\\ufe0e\\ufe0f]"),Ln=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Un="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Cn={};
|
||||
Cn["[object Float32Array]"]=Cn["[object Float64Array]"]=Cn["[object Int8Array]"]=Cn["[object Int16Array]"]=Cn["[object Int32Array]"]=Cn["[object Uint8Array]"]=Cn["[object Uint8ClampedArray]"]=Cn["[object Uint16Array]"]=Cn["[object Uint32Array]"]=true,Cn["[object Arguments]"]=Cn["[object Array]"]=Cn["[object ArrayBuffer]"]=Cn["[object Boolean]"]=Cn["[object DataView]"]=Cn["[object Date]"]=Cn["[object Error]"]=Cn["[object Function]"]=Cn["[object Map]"]=Cn["[object Number]"]=Cn["[object Object]"]=Cn["[object RegExp]"]=Cn["[object Set]"]=Cn["[object String]"]=Cn["[object WeakMap]"]=false;
|
||||
var Dn={};Dn["[object Arguments]"]=Dn["[object Array]"]=Dn["[object ArrayBuffer]"]=Dn["[object DataView]"]=Dn["[object Boolean]"]=Dn["[object Date]"]=Dn["[object Float32Array]"]=Dn["[object Float64Array]"]=Dn["[object Int8Array]"]=Dn["[object Int16Array]"]=Dn["[object Int32Array]"]=Dn["[object Map]"]=Dn["[object Number]"]=Dn["[object Object]"]=Dn["[object RegExp]"]=Dn["[object Set]"]=Dn["[object String]"]=Dn["[object Symbol]"]=Dn["[object Uint8Array]"]=Dn["[object Uint8ClampedArray]"]=Dn["[object Uint16Array]"]=Dn["[object Uint32Array]"]=true,
|
||||
Dn["[object Error]"]=Dn["[object Function]"]=Dn["[object WeakMap]"]=false;var Mn,Tn={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},$n=parseFloat,Fn=parseInt,Nn=typeof global=="object"&&global&&global.Object===Object&&global,Pn=typeof self=="object"&&self&&self.Object===Object&&self,Zn=Nn||Pn||Function("return this")(),qn=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Vn=qn&&typeof module=="object"&&module&&!module.nodeType&&module,Kn=Vn&&Vn.exports===qn,Gn=Kn&&Nn.process;
|
||||
n:{try{Mn=Gn&&Gn.binding&&Gn.binding("util");break n}catch(n){}Mn=void 0}var Hn=Mn&&Mn.isArrayBuffer,Jn=Mn&&Mn.isDate,Yn=Mn&&Mn.isMap,Qn=Mn&&Mn.isRegExp,Xn=Mn&&Mn.isSet,nt=Mn&&Mn.isTypedArray,tt=j("length"),rt=w({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I",
|
||||
"\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C",
|
||||
"\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i",
|
||||
"\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S",
|
||||
"\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe",
|
||||
"\u0149":"'n","\u017f":"s"}),et=w({"&":"&","<":"<",">":">",'"':""","'":"'"}),ut=w({"&":"&","<":"<",">":">",""":'"',"'":"'"}),it=function w(En){function On(n){if(xu(n)&&!af(n)&&!(n instanceof Mn)){if(n instanceof zn)return n;if(ci.call(n,"__wrapped__"))return Pe(n)}return new zn(n)}function Sn(){}function zn(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=F}function Mn(n){this.__wrapped__=n,this.__actions__=[],this.__dir__=1,
|
||||
this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Tn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Nn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function Pn(n){var t=-1,r=null==n?0:n.length;for(this.clear();++t<r;){var e=n[t];this.set(e[0],e[1])}}function qn(n){var t=-1,r=null==n?0:n.length;for(this.__data__=new Pn;++t<r;)this.add(n[t])}function Vn(n){
|
||||
this.size=(this.__data__=new Nn(n)).size}function Gn(n,t){var r,e=af(n),u=!e&&cf(n),i=!e&&!u&&sf(n),o=!e&&!u&&!i&&gf(n),u=(e=e||u||i||o)?E(n.length,ri):[],f=u.length;for(r in n)!t&&!ci.call(n,r)||e&&("length"==r||i&&("offset"==r||"parent"==r)||o&&("buffer"==r||"byteLength"==r||"byteOffset"==r)||Re(r,f))||u.push(r);return u}function tt(n){var t=n.length;return t?n[cr(0,t-1)]:F}function ot(n,t){return Te(Mr(n),gt(t,0,n.length))}function ft(n){return Te(Mr(n))}function ct(n,t,r){(r===F||hu(n[t],r))&&(r!==F||t in n)||_t(n,t,r);
|
||||
}function at(n,t,r){var e=n[t];ci.call(n,t)&&hu(e,r)&&(r!==F||t in n)||_t(n,t,r)}function lt(n,t){for(var r=n.length;r--;)if(hu(n[r][0],t))return r;return-1}function st(n,t,r,e){return oo(n,function(n,u,i){t(e,n,r(n),i)}),e}function ht(n,t){return n&&Tr(t,Lu(t),n)}function pt(n,t){return n&&Tr(t,Uu(t),n)}function _t(n,t,r){"__proto__"==t&&Ei?Ei(n,t,{configurable:true,enumerable:true,value:r,writable:true}):n[t]=r}function vt(n,t){for(var r=-1,e=t.length,u=Hu(e),i=null==n;++r<e;)u[r]=i?F:Wu(n,t[r]);return u;
|
||||
}function gt(n,t,r){return n===n&&(r!==F&&(n=n<=r?n:r),t!==F&&(n=n>=t?n:t)),n}function dt(n,t,r,e,i,o){var f,c=1&t,a=2&t,l=4&t;if(r&&(f=i?r(n,e,i,o):r(n)),f!==F)return f;if(!bu(n))return n;if(e=af(n)){if(f=Ee(n),!c)return Mr(n,f)}else{var s=yo(n),h="[object Function]"==s||"[object GeneratorFunction]"==s;if(sf(n))return Wr(n,c);if("[object Object]"==s||"[object Arguments]"==s||h&&!i){if(f=a||h?{}:Oe(n),!c)return a?Fr(n,pt(f,n)):$r(n,ht(f,n))}else{if(!Dn[s])return i?n:{};f=Se(n,s,dt,c)}}if(o||(o=new Vn),
|
||||
i=o.get(n))return i;o.set(n,f);var a=l?a?ye:de:a?Uu:Lu,p=e?F:a(n);return u(p||n,function(e,u){p&&(u=e,e=n[u]),at(f,u,dt(e,t,r,u,n,o))}),f}function yt(n){var t=Lu(n);return function(r){return bt(r,n,t)}}function bt(n,t,r){var e=r.length;if(null==n)return!e;for(n=ni(n);e--;){var u=r[e],i=t[u],o=n[u];if(o===F&&!(u in n)||!i(o))return false}return true}function xt(n,t,r){if(typeof n!="function")throw new ei("Expected a function");return jo(function(){n.apply(F,r)},t)}function jt(n,t,r,e){var u=-1,i=c,o=true,f=n.length,s=[],h=t.length;
|
||||
if(!f)return s;r&&(t=l(t,S(r))),e?(i=a,o=false):200<=t.length&&(i=R,o=false,t=new qn(t));n:for(;++u<f;){var p=n[u],_=null==r?p:r(p),p=e||0!==p?p:0;if(o&&_===_){for(var v=h;v--;)if(t[v]===_)continue n;s.push(p)}else i(t,_,e)||s.push(p)}return s}function wt(n,t){var r=true;return oo(n,function(n,e,u){return r=!!t(n,e,u)}),r}function mt(n,t,r){for(var e=-1,u=n.length;++e<u;){var i=n[e],o=t(i);if(null!=o&&(f===F?o===o&&!Au(o):r(o,f)))var f=o,c=i}return c}function At(n,t){var r=[];return oo(n,function(n,e,u){
|
||||
t(n,e,u)&&r.push(n)}),r}function kt(n,t,r,e,u){var i=-1,o=n.length;for(r||(r=Ie),u||(u=[]);++i<o;){var f=n[i];0<t&&r(f)?1<t?kt(f,t-1,r,e,u):s(u,f):e||(u[u.length]=f)}return u}function Et(n,t){return n&&co(n,t,Lu)}function Ot(n,t){return n&&ao(n,t,Lu)}function St(n,t){return f(t,function(t){return gu(n[t])})}function It(n,t){t=Rr(t,n);for(var r=0,e=t.length;null!=n&&r<e;)n=n[$e(t[r++])];return r&&r==e?n:F}function Rt(n,t,r){return t=t(n),af(n)?t:s(t,r(n))}function zt(n){if(null==n)n=n===F?"[object Undefined]":"[object Null]";else if(ki&&ki in ni(n)){
|
||||
var t=ci.call(n,ki),r=n[ki];try{n[ki]=F;var e=true}catch(n){}var u=si.call(n);e&&(t?n[ki]=r:delete n[ki]),n=u}else n=si.call(n);return n}function Wt(n,t){return n>t}function Bt(n,t){return null!=n&&ci.call(n,t)}function Lt(n,t){return null!=n&&t in ni(n)}function Ut(n,t,r){for(var e=r?a:c,u=n[0].length,i=n.length,o=i,f=Hu(i),s=1/0,h=[];o--;){var p=n[o];o&&t&&(p=l(p,S(t))),s=Mi(p.length,s),f[o]=!r&&(t||120<=u&&120<=p.length)?new qn(o&&p):F}var p=n[0],_=-1,v=f[0];n:for(;++_<u&&h.length<s;){var g=p[_],d=t?t(g):g,g=r||0!==g?g:0;
|
||||
if(v?!R(v,d):!e(h,d,r)){for(o=i;--o;){var y=f[o];if(y?!R(y,d):!e(n[o],d,r))continue n}v&&v.push(d),h.push(g)}}return h}function Ct(n,t,r){var e={};return Et(n,function(n,u,i){t(e,r(n),u,i)}),e}function Dt(n,t,e){return t=Rr(t,n),n=2>t.length?n:It(n,vr(t,0,-1)),t=null==n?n:n[$e(Ge(t))],null==t?F:r(t,n,e)}function Mt(n){return xu(n)&&"[object Arguments]"==zt(n)}function Tt(n){return xu(n)&&"[object ArrayBuffer]"==zt(n)}function $t(n){return xu(n)&&"[object Date]"==zt(n)}function Ft(n,t,r,e,u){if(n===t)t=true;else if(null==n||null==t||!xu(n)&&!xu(t))t=n!==n&&t!==t;else n:{
|
||||
var i=af(n),o=af(t),f=i?"[object Array]":yo(n),c=o?"[object Array]":yo(t),f="[object Arguments]"==f?"[object Object]":f,c="[object Arguments]"==c?"[object Object]":c,a="[object Object]"==f,o="[object Object]"==c;if((c=f==c)&&sf(n)){if(!sf(t)){t=false;break n}i=true,a=false}if(c&&!a)u||(u=new Vn),t=i||gf(n)?_e(n,t,r,e,Ft,u):ve(n,t,f,r,e,Ft,u);else{if(!(1&r)&&(i=a&&ci.call(n,"__wrapped__"),f=o&&ci.call(t,"__wrapped__"),i||f)){n=i?n.value():n,t=f?t.value():t,u||(u=new Vn),t=Ft(n,t,r,e,u);break n}if(c)t:if(u||(u=new Vn),
|
||||
i=1&r,f=de(n),o=f.length,c=de(t).length,o==c||i){for(a=o;a--;){var l=f[a];if(!(i?l in t:ci.call(t,l))){t=false;break t}}if((c=u.get(n))&&u.get(t))t=c==t;else{c=true,u.set(n,t),u.set(t,n);for(var s=i;++a<o;){var l=f[a],h=n[l],p=t[l];if(e)var _=i?e(p,h,l,t,n,u):e(h,p,l,n,t,u);if(_===F?h!==p&&!Ft(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l)}c&&!s&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)),
|
||||
u.delete(n),u.delete(t),t=c}}else t=false;else t=false}}return t}function Nt(n){return xu(n)&&"[object Map]"==yo(n)}function Pt(n,t,r,e){var u=r.length,i=u,o=!e;if(null==n)return!i;for(n=ni(n);u--;){var f=r[u];if(o&&f[2]?f[1]!==n[f[0]]:!(f[0]in n))return false}for(;++u<i;){var f=r[u],c=f[0],a=n[c],l=f[1];if(o&&f[2]){if(a===F&&!(c in n))return false}else{if(f=new Vn,e)var s=e(a,l,c,n,t,f);if(s===F?!Ft(l,a,3,e,f):!s)return false}}return true}function Zt(n){return!(!bu(n)||li&&li in n)&&(gu(n)?_i:xn).test(Fe(n))}function qt(n){
|
||||
return xu(n)&&"[object RegExp]"==zt(n)}function Vt(n){return xu(n)&&"[object Set]"==yo(n)}function Kt(n){return xu(n)&&yu(n.length)&&!!Cn[zt(n)]}function Gt(n){return typeof n=="function"?n:null==n?Nu:typeof n=="object"?af(n)?Xt(n[0],n[1]):Qt(n):Vu(n)}function Ht(n){if(!Le(n))return Ci(n);var t,r=[];for(t in ni(n))ci.call(n,t)&&"constructor"!=t&&r.push(t);return r}function Jt(n,t){return n<t}function Yt(n,t){var r=-1,e=pu(n)?Hu(n.length):[];return oo(n,function(n,u,i){e[++r]=t(n,u,i)}),e}function Qt(n){
|
||||
var t=me(n);return 1==t.length&&t[0][2]?Ue(t[0][0],t[0][1]):function(r){return r===n||Pt(r,n,t)}}function Xt(n,t){return We(n)&&t===t&&!bu(t)?Ue($e(n),t):function(r){var e=Wu(r,n);return e===F&&e===t?Bu(r,n):Ft(t,e,3)}}function nr(n,t,r,e,u){n!==t&&co(t,function(i,o){if(bu(i)){u||(u=new Vn);var f=u,c=n[o],a=t[o],l=f.get(a);if(l)ct(n,o,l);else{var l=e?e(c,a,o+"",n,t,f):F,s=l===F;if(s){var h=af(a),p=!h&&sf(a),_=!h&&!p&&gf(a),l=a;h||p||_?af(c)?l=c:_u(c)?l=Mr(c):p?(s=false,l=Wr(a,true)):_?(s=false,l=Lr(a,true)):l=[]:wu(a)||cf(a)?(l=c,
|
||||
cf(c)?l=Ru(c):(!bu(c)||r&&gu(c))&&(l=Oe(a))):s=false}s&&(f.set(a,l),nr(l,a,r,e,f),f.delete(a)),ct(n,o,l)}}else f=e?e(n[o],i,o+"",n,t,u):F,f===F&&(f=i),ct(n,o,f)},Uu)}function tr(n,t){var r=n.length;if(r)return t+=0>t?r:0,Re(t,r)?n[t]:F}function rr(n,t,r){var e=-1;return t=l(t.length?t:[Nu],S(je())),n=Yt(n,function(n){return{a:l(t,function(t){return t(n)}),b:++e,c:n}}),A(n,function(n,t){var e;n:{e=-1;for(var u=n.a,i=t.a,o=u.length,f=r.length;++e<o;){var c=Ur(u[e],i[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);
|
||||
break n}}e=n.b-t.b}return e})}function er(n,t){return ur(n,t,function(t,r){return Bu(n,r)})}function ur(n,t,r){for(var e=-1,u=t.length,i={};++e<u;){var o=t[e],f=It(n,o);r(f,o)&&pr(i,Rr(o,n),f)}return i}function ir(n){return function(t){return It(t,n)}}function or(n,t,r,e){var u=e?y:d,i=-1,o=t.length,f=n;for(n===t&&(t=Mr(t)),r&&(f=l(n,S(r)));++i<o;)for(var c=0,a=t[i],a=r?r(a):a;-1<(c=u(f,a,c,e));)f!==n&&wi.call(f,c,1),wi.call(n,c,1);return n}function fr(n,t){for(var r=n?t.length:0,e=r-1;r--;){var u=t[r];
|
||||
if(r==e||u!==i){var i=u;Re(u)?wi.call(n,u,1):mr(n,u)}}}function cr(n,t){return n+zi(Fi()*(t-n+1))}function ar(n,t){var r="";if(!n||1>t||9007199254740991<t)return r;do t%2&&(r+=n),(t=zi(t/2))&&(n+=n);while(t);return r}function lr(n,t){return wo(Ce(n,t,Nu),n+"")}function sr(n){return tt(Du(n))}function hr(n,t){var r=Du(n);return Te(r,gt(t,0,r.length))}function pr(n,t,r,e){if(!bu(n))return n;t=Rr(t,n);for(var u=-1,i=t.length,o=i-1,f=n;null!=f&&++u<i;){var c=$e(t[u]),a=r;if(u!=o){var l=f[c],a=e?e(l,c,f):F;
|
||||
a===F&&(a=bu(l)?l:Re(t[u+1])?[]:{})}at(f,c,a),f=f[c]}return n}function _r(n){return Te(Du(n))}function vr(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Hu(u);++e<u;)r[e]=n[e+t];return r}function gr(n,t){var r;return oo(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function dr(n,t,r){var e=0,u=null==n?e:n.length;if(typeof t=="number"&&t===t&&2147483647>=u){for(;e<u;){var i=e+u>>>1,o=n[i];null!==o&&!Au(o)&&(r?o<=t:o<t)?e=i+1:u=i}return u}return yr(n,t,Nu,r);
|
||||
}function yr(n,t,r,e){t=r(t);for(var u=0,i=null==n?0:n.length,o=t!==t,f=null===t,c=Au(t),a=t===F;u<i;){var l=zi((u+i)/2),s=r(n[l]),h=s!==F,p=null===s,_=s===s,v=Au(s);(o?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=t:s<t)?u=l+1:i=l}return Mi(i,4294967294)}function br(n,t){for(var r=-1,e=n.length,u=0,i=[];++r<e;){var o=n[r],f=t?t(o):o;if(!r||!hu(f,c)){var c=f;i[u++]=0===o?0:o}}return i}function xr(n){return typeof n=="number"?n:Au(n)?P:+n}function jr(n){if(typeof n=="string")return n;
|
||||
if(af(n))return l(n,jr)+"";if(Au(n))return uo?uo.call(n):"";var t=n+"";return"0"==t&&1/n==-N?"-0":t}function wr(n,t,r){var e=-1,u=c,i=n.length,o=true,f=[],l=f;if(r)o=false,u=a;else if(200<=i){if(u=t?null:po(n))return D(u);o=false,u=R,l=new qn}else l=t?[]:f;n:for(;++e<i;){var s=n[e],h=t?t(s):s,s=r||0!==s?s:0;if(o&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue n;t&&l.push(h),f.push(s)}else u(l,h,r)||(l!==f&&l.push(h),f.push(s))}return f}function mr(n,t){return t=Rr(t,n),n=2>t.length?n:It(n,vr(t,0,-1)),
|
||||
null==n||delete n[$e(Ge(t))]}function Ar(n,t,r,e){for(var u=n.length,i=e?u:-1;(e?i--:++i<u)&&t(n[i],i,n););return r?vr(n,e?0:i,e?i+1:u):vr(n,e?i+1:0,e?u:i)}function kr(n,t){var r=n;return r instanceof Mn&&(r=r.value()),h(t,function(n,t){return t.func.apply(t.thisArg,s([n],t.args))},r)}function Er(n,t,r){var e=n.length;if(2>e)return e?wr(n[0]):[];for(var u=-1,i=Hu(e);++u<e;)for(var o=n[u],f=-1;++f<e;)f!=u&&(i[u]=jt(i[u]||o,n[f],t,r));return wr(kt(i,1),t,r)}function Or(n,t,r){for(var e=-1,u=n.length,i=t.length,o={};++e<u;)r(o,n[e],e<i?t[e]:F);
|
||||
return o}function Sr(n){return _u(n)?n:[]}function Ir(n){return typeof n=="function"?n:Nu}function Rr(n,t){return af(n)?n:We(n,t)?[n]:mo(zu(n))}function zr(n,t,r){var e=n.length;return r=r===F?e:r,!t&&r>=e?n:vr(n,t,r)}function Wr(n,t){if(t)return n.slice();var r=n.length,r=yi?yi(r):new n.constructor(r);return n.copy(r),r}function Br(n){var t=new n.constructor(n.byteLength);return new di(t).set(new di(n)),t}function Lr(n,t){return new n.constructor(t?Br(n.buffer):n.buffer,n.byteOffset,n.length)}function Ur(n,t){
|
||||
if(n!==t){var r=n!==F,e=null===n,u=n===n,i=Au(n),o=t!==F,f=null===t,c=t===t,a=Au(t);if(!f&&!a&&!i&&n>t||i&&o&&c&&!f&&!a||e&&o&&c||!r&&c||!u)return 1;if(!e&&!i&&!a&&n<t||a&&r&&u&&!e&&!i||f&&r&&u||!o&&u||!c)return-1}return 0}function Cr(n,t,r,e){var u=-1,i=n.length,o=r.length,f=-1,c=t.length,a=Di(i-o,0),l=Hu(c+a);for(e=!e;++f<c;)l[f]=t[f];for(;++u<o;)(e||u<i)&&(l[r[u]]=n[u]);for(;a--;)l[f++]=n[u++];return l}function Dr(n,t,r,e){var u=-1,i=n.length,o=-1,f=r.length,c=-1,a=t.length,l=Di(i-f,0),s=Hu(l+a);
|
||||
for(e=!e;++u<l;)s[u]=n[u];for(l=u;++c<a;)s[l+c]=t[c];for(;++o<f;)(e||u<i)&&(s[l+r[o]]=n[u++]);return s}function Mr(n,t){var r=-1,e=n.length;for(t||(t=Hu(e));++r<e;)t[r]=n[r];return t}function Tr(n,t,r,e){var u=!r;r||(r={});for(var i=-1,o=t.length;++i<o;){var f=t[i],c=e?e(r[f],n[f],f,r,n):F;c===F&&(c=n[f]),u?_t(r,f,c):at(r,f,c)}return r}function $r(n,t){return Tr(n,vo(n),t)}function Fr(n,t){return Tr(n,go(n),t)}function Nr(n,t){return function(r,u){var i=af(r)?e:st,o=t?t():{};return i(r,n,je(u,2),o);
|
||||
}}function Pr(n){return lr(function(t,r){var e=-1,u=r.length,i=1<u?r[u-1]:F,o=2<u?r[2]:F,i=3<n.length&&typeof i=="function"?(u--,i):F;for(o&&ze(r[0],r[1],o)&&(i=3>u?F:i,u=1),t=ni(t);++e<u;)(o=r[e])&&n(t,o,e,i);return t})}function Zr(n,t){return function(r,e){if(null==r)return r;if(!pu(r))return n(r,e);for(var u=r.length,i=t?u:-1,o=ni(r);(t?i--:++i<u)&&false!==e(o[i],i,o););return r}}function qr(n){return function(t,r,e){var u=-1,i=ni(t);e=e(t);for(var o=e.length;o--;){var f=e[n?o:++u];if(false===r(i[f],f,i))break;
|
||||
}return t}}function Vr(n,t,r){function e(){return(this&&this!==Zn&&this instanceof e?i:n).apply(u?r:this,arguments)}var u=1&t,i=Hr(n);return e}function Kr(n){return function(t){t=zu(t);var r=Bn.test(t)?$(t):F,e=r?r[0]:t.charAt(0);return t=r?zr(r,1).join(""):t.slice(1),e[n]()+t}}function Gr(n){return function(t){return h($u(Tu(t).replace(In,"")),n,"")}}function Hr(n){return function(){var t=arguments;switch(t.length){case 0:return new n;case 1:return new n(t[0]);case 2:return new n(t[0],t[1]);case 3:
|
||||
return new n(t[0],t[1],t[2]);case 4:return new n(t[0],t[1],t[2],t[3]);case 5:return new n(t[0],t[1],t[2],t[3],t[4]);case 6:return new n(t[0],t[1],t[2],t[3],t[4],t[5]);case 7:return new n(t[0],t[1],t[2],t[3],t[4],t[5],t[6])}var r=io(n.prototype),t=n.apply(r,t);return bu(t)?t:r}}function Jr(n,t,e){function u(){for(var o=arguments.length,f=Hu(o),c=o,a=xe(u);c--;)f[c]=arguments[c];return c=3>o&&f[0]!==a&&f[o-1]!==a?[]:C(f,a),o-=c.length,o<e?fe(n,t,Xr,u.placeholder,F,f,c,F,F,e-o):r(this&&this!==Zn&&this instanceof u?i:n,this,f);
|
||||
}var i=Hr(n);return u}function Yr(n){return function(t,r,e){var u=ni(t);if(!pu(t)){var i=je(r,3);t=Lu(t),r=function(n){return i(u[n],n,u)}}return r=n(t,r,e),-1<r?u[i?t[r]:r]:F}}function Qr(n){return ge(function(t){var r=t.length,e=r,u=zn.prototype.thru;for(n&&t.reverse();e--;){var i=t[e];if(typeof i!="function")throw new ei("Expected a function");if(u&&!o&&"wrapper"==be(i))var o=new zn([],true)}for(e=o?e:r;++e<r;)var i=t[e],u=be(i),f="wrapper"==u?_o(i):F,o=f&&Be(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?o[be(f[0])].apply(o,f[3]):1==i.length&&Be(i)?o[u]():o.thru(i);
|
||||
return function(){var n=arguments,e=n[0];if(o&&1==n.length&&af(e))return o.plant(e).value();for(var u=0,n=r?t[u].apply(this,n):e;++u<r;)n=t[u].call(this,n);return n}})}function Xr(n,t,r,e,u,i,o,f,c,a){function l(){for(var d=arguments.length,y=Hu(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=xe(l),b=y.length;for(x=0;b--;)y[b]===j&&++x}if(e&&(y=Cr(y,e,u,_)),i&&(y=Dr(y,i,o,_)),d-=x,_&&d<a)return j=C(y,j),fe(n,t,Xr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[n]:n,d=y.length,f){x=y.length;for(var w=Mi(f.length,x),m=Mr(y);w--;){
|
||||
var A=f[w];y[w]=Re(A,x)?m[A]:F}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==Zn&&this instanceof l&&(b=g||Hr(b)),b.apply(j,y)}var s=128&t,h=1&t,p=2&t,_=24&t,v=512&t,g=p?F:Hr(n);return l}function ne(n,t){return function(r,e){return Ct(r,n,t(e))}}function te(n,t){return function(r,e){var u;if(r===F&&e===F)return t;if(r!==F&&(u=r),e!==F){if(u===F)return e;typeof r=="string"||typeof e=="string"?(r=jr(r),e=jr(e)):(r=xr(r),e=xr(e)),u=n(r,e)}return u}}function re(n){return ge(function(t){
|
||||
return t=l(t,S(je())),lr(function(e){var u=this;return n(t,function(n){return r(n,u,e)})})})}function ee(n,t){t=t===F?" ":jr(t);var r=t.length;return 2>r?r?ar(t,n):t:(r=ar(t,Ri(n/T(t))),Bn.test(t)?zr($(r),0,n).join(""):r.slice(0,n))}function ue(n,t,e,u){function i(){for(var t=-1,c=arguments.length,a=-1,l=u.length,s=Hu(l+c),h=this&&this!==Zn&&this instanceof i?f:n;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++t];return r(h,o?e:this,s)}var o=1&t,f=Hr(n);return i}function ie(n){return function(t,r,e){
|
||||
e&&typeof e!="number"&&ze(t,r,e)&&(r=e=F),t=Eu(t),r===F?(r=t,t=0):r=Eu(r),e=e===F?t<r?1:-1:Eu(e);var u=-1;r=Di(Ri((r-t)/(e||1)),0);for(var i=Hu(r);r--;)i[n?r:++u]=t,t+=e;return i}}function oe(n){return function(t,r){return typeof t=="string"&&typeof r=="string"||(t=Iu(t),r=Iu(r)),n(t,r)}}function fe(n,t,r,e,u,i,o,f,c,a){var l=8&t,s=l?o:F;o=l?F:o;var h=l?i:F;return i=l?F:i,t=(t|(l?32:64))&~(l?64:32),4&t||(t&=-4),u=[n,t,u,h,s,i,o,f,c,a],r=r.apply(F,u),Be(n)&&xo(r,u),r.placeholder=e,De(r,n,t)}function ce(n){
|
||||
var t=Xu[n];return function(n,r){if(n=Iu(n),r=null==r?0:Mi(Ou(r),292)){var e=(zu(n)+"e").split("e"),e=t(e[0]+"e"+(+e[1]+r)),e=(zu(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return t(n)}}function ae(n){return function(t){var r=yo(t);return"[object Map]"==r?L(t):"[object Set]"==r?M(t):O(t,n(t))}}function le(n,t,r,e,u,i,o,f){var c=2&t;if(!c&&typeof n!="function")throw new ei("Expected a function");var a=e?e.length:0;if(a||(t&=-97,e=u=F),o=o===F?o:Di(Ou(o),0),f=f===F?f:Ou(f),a-=u?u.length:0,64&t){
|
||||
var l=e,s=u;e=u=F}var h=c?F:_o(n);return i=[n,t,r,e,u,l,s,i,o,f],h&&(r=i[1],n=h[1],t=r|n,e=128==n&&8==r||128==n&&256==r&&i[7].length<=h[8]||384==n&&h[7].length<=h[8]&&8==r,131>t||e)&&(1&n&&(i[2]=h[2],t|=1&r?0:4),(r=h[3])&&(e=i[3],i[3]=e?Cr(e,r,h[4]):r,i[4]=e?C(i[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=i[5],i[5]=e?Dr(e,r,h[6]):r,i[6]=e?C(i[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(i[7]=r),128&n&&(i[8]=null==i[8]?h[8]:Mi(i[8],h[8])),null==i[9]&&(i[9]=h[9]),i[0]=h[0],i[1]=t),n=i[0],t=i[1],
|
||||
r=i[2],e=i[3],u=i[4],f=i[9]=i[9]===F?c?0:n.length:Di(i[9]-a,0),!f&&24&t&&(t&=-25),De((h?lo:xo)(t&&1!=t?8==t||16==t?Jr(n,t,f):32!=t&&33!=t||u.length?Xr.apply(F,i):ue(n,t,r,e):Vr(n,t,r),i),n,t)}function se(n,t,r,e){return n===F||hu(n,ii[r])&&!ci.call(e,r)?t:n}function he(n,t,r,e,u,i){return bu(n)&&bu(t)&&(i.set(t,n),nr(n,t,F,he,i),i.delete(t)),n}function pe(n){return wu(n)?F:n}function _e(n,t,r,e,u,i){var o=1&r,f=n.length,c=t.length;if(f!=c&&!(o&&c>f))return false;if((c=i.get(n))&&i.get(t))return c==t;var c=-1,a=true,l=2&r?new qn:F;
|
||||
for(i.set(n,t),i.set(t,n);++c<f;){var s=n[c],h=t[c];if(e)var p=o?e(h,s,c,t,n,i):e(s,h,c,n,t,i);if(p!==F){if(p)continue;a=false;break}if(l){if(!_(t,function(n,t){if(!R(l,t)&&(s===n||u(s,n,r,e,i)))return l.push(t)})){a=false;break}}else if(s!==h&&!u(s,h,r,e,i)){a=false;break}}return i.delete(n),i.delete(t),a}function ve(n,t,r,e,u,i,o){switch(r){case"[object DataView]":if(n.byteLength!=t.byteLength||n.byteOffset!=t.byteOffset)break;n=n.buffer,t=t.buffer;case"[object ArrayBuffer]":if(n.byteLength!=t.byteLength||!i(new di(n),new di(t)))break;
|
||||
return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return hu(+n,+t);case"[object Error]":return n.name==t.name&&n.message==t.message;case"[object RegExp]":case"[object String]":return n==t+"";case"[object Map]":var f=L;case"[object Set]":if(f||(f=D),n.size!=t.size&&!(1&e))break;return(r=o.get(n))?r==t:(e|=2,o.set(n,t),t=_e(f(n),f(t),e,u,i,o),o.delete(n),t);case"[object Symbol]":if(eo)return eo.call(n)==eo.call(t)}return false}function ge(n){return wo(Ce(n,F,Ve),n+"")}function de(n){
|
||||
return Rt(n,Lu,vo)}function ye(n){return Rt(n,Uu,go)}function be(n){for(var t=n.name+"",r=Ji[t],e=ci.call(Ji,t)?r.length:0;e--;){var u=r[e],i=u.func;if(null==i||i==n)return u.name}return t}function xe(n){return(ci.call(On,"placeholder")?On:n).placeholder}function je(){var n=On.iteratee||Pu,n=n===Pu?Gt:n;return arguments.length?n(arguments[0],arguments[1]):n}function we(n,t){var r=n.__data__,e=typeof t;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==t:null===t)?r[typeof t=="string"?"string":"hash"]:r.map;
|
||||
}function me(n){for(var t=Lu(n),r=t.length;r--;){var e=t[r],u=n[e];t[r]=[e,u,u===u&&!bu(u)]}return t}function Ae(n,t){var r=null==n?F:n[t];return Zt(r)?r:F}function ke(n,t,r){t=Rr(t,n);for(var e=-1,u=t.length,i=false;++e<u;){var o=$e(t[e]);if(!(i=null!=n&&r(n,o)))break;n=n[o]}return i||++e!=u?i:(u=null==n?0:n.length,!!u&&yu(u)&&Re(o,u)&&(af(n)||cf(n)))}function Ee(n){var t=n.length,r=n.constructor(t);return t&&"string"==typeof n[0]&&ci.call(n,"index")&&(r.index=n.index,r.input=n.input),r}function Oe(n){
|
||||
return typeof n.constructor!="function"||Le(n)?{}:io(bi(n))}function Se(r,e,u,i){var o=r.constructor;switch(e){case"[object ArrayBuffer]":return Br(r);case"[object Boolean]":case"[object Date]":return new o(+r);case"[object DataView]":return e=i?Br(r.buffer):r.buffer,new r.constructor(e,r.byteOffset,r.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":
|
||||
case"[object Uint16Array]":case"[object Uint32Array]":return Lr(r,i);case"[object Map]":return e=i?u(L(r),1):L(r),h(e,n,new r.constructor);case"[object Number]":case"[object String]":return new o(r);case"[object RegExp]":return e=new r.constructor(r.source,dn.exec(r)),e.lastIndex=r.lastIndex,e;case"[object Set]":return e=i?u(D(r),1):D(r),h(e,t,new r.constructor);case"[object Symbol]":return eo?ni(eo.call(r)):{}}}function Ie(n){return af(n)||cf(n)||!!(mi&&n&&n[mi])}function Re(n,t){return t=null==t?9007199254740991:t,
|
||||
!!t&&(typeof n=="number"||wn.test(n))&&-1<n&&0==n%1&&n<t}function ze(n,t,r){if(!bu(r))return false;var e=typeof t;return!!("number"==e?pu(r)&&Re(t,r.length):"string"==e&&t in r)&&hu(r[t],n)}function We(n,t){if(af(n))return false;var r=typeof n;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=n&&!Au(n))||(rn.test(n)||!tn.test(n)||null!=t&&n in ni(t))}function Be(n){var t=be(n),r=On[t];return typeof r=="function"&&t in Mn.prototype&&(n===r||(t=_o(r),!!t&&n===t[0]))}function Le(n){var t=n&&n.constructor;
|
||||
return n===(typeof t=="function"&&t.prototype||ii)}function Ue(n,t){return function(r){return null!=r&&(r[n]===t&&(t!==F||n in ni(r)))}}function Ce(n,t,e){return t=Di(t===F?n.length-1:t,0),function(){for(var u=arguments,i=-1,o=Di(u.length-t,0),f=Hu(o);++i<o;)f[i]=u[t+i];for(i=-1,o=Hu(t+1);++i<t;)o[i]=u[i];return o[t]=e(f),r(n,this,o)}}function De(n,t,r){var e=t+"";t=wo;var u,i=Ne;return u=(u=e.match(hn))?u[1].split(pn):[],r=i(u,r),(i=r.length)&&(u=i-1,r[u]=(1<i?"& ":"")+r[u],r=r.join(2<i?", ":" "),
|
||||
e=e.replace(sn,"{\n/* [wrapped with "+r+"] */\n")),t(n,e)}function Me(n){var t=0,r=0;return function(){var e=Ti(),u=16-(e-r);if(r=e,0<u){if(800<=++t)return arguments[0]}else t=0;return n.apply(F,arguments)}}function Te(n,t){var r=-1,e=n.length,u=e-1;for(t=t===F?e:t;++r<t;){var e=cr(r,u),i=n[e];n[e]=n[r],n[r]=i}return n.length=t,n}function $e(n){if(typeof n=="string"||Au(n))return n;var t=n+"";return"0"==t&&1/n==-N?"-0":t}function Fe(n){if(null!=n){try{return fi.call(n)}catch(n){}return n+""}return"";
|
||||
}function Ne(n,t){return u(Z,function(r){var e="_."+r[0];t&r[1]&&!c(n,e)&&n.push(e)}),n.sort()}function Pe(n){if(n instanceof Mn)return n.clone();var t=new zn(n.__wrapped__,n.__chain__);return t.__actions__=Mr(n.__actions__),t.__index__=n.__index__,t.__values__=n.__values__,t}function Ze(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Ou(r),0>r&&(r=Di(e+r,0)),g(n,je(t,3),r)):-1}function qe(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e-1;return r!==F&&(u=Ou(r),u=0>r?Di(e+u,0):Mi(u,e-1)),
|
||||
g(n,je(t,3),u,true)}function Ve(n){return(null==n?0:n.length)?kt(n,1):[]}function Ke(n){return n&&n.length?n[0]:F}function Ge(n){var t=null==n?0:n.length;return t?n[t-1]:F}function He(n,t){return n&&n.length&&t&&t.length?or(n,t):n}function Je(n){return null==n?n:Ni.call(n)}function Ye(n){if(!n||!n.length)return[];var t=0;return n=f(n,function(n){if(_u(n))return t=Di(n.length,t),true}),E(t,function(t){return l(n,j(t))})}function Qe(n,t){if(!n||!n.length)return[];var e=Ye(n);return null==t?e:l(e,function(n){
|
||||
return r(t,F,n)})}function Xe(n){return n=On(n),n.__chain__=true,n}function nu(n,t){return t(n)}function tu(){return this}function ru(n,t){return(af(n)?u:oo)(n,je(t,3))}function eu(n,t){return(af(n)?i:fo)(n,je(t,3))}function uu(n,t){return(af(n)?l:Yt)(n,je(t,3))}function iu(n,t,r){return t=r?F:t,t=n&&null==t?n.length:t,le(n,128,F,F,F,F,t)}function ou(n,t){var r;if(typeof t!="function")throw new ei("Expected a function");return n=Ou(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=F),
|
||||
r}}function fu(n,t,r){return t=r?F:t,n=le(n,8,F,F,F,F,F,t),n.placeholder=fu.placeholder,n}function cu(n,t,r){return t=r?F:t,n=le(n,16,F,F,F,F,F,t),n.placeholder=cu.placeholder,n}function au(n,t,r){function e(t){var r=c,e=a;return c=a=F,_=t,s=n.apply(e,r)}function u(n){var r=n-p;return n-=_,p===F||r>=t||0>r||g&&n>=l}function i(){var n=Jo();if(u(n))return o(n);var r,e=jo;r=n-_,n=t-(n-p),r=g?Mi(n,l-r):n,h=e(i,r)}function o(n){return h=F,d&&c?e(n):(c=a=F,s)}function f(){var n=Jo(),r=u(n);if(c=arguments,
|
||||
a=this,p=n,r){if(h===F)return _=n=p,h=jo(i,t),v?e(n):s;if(g)return h=jo(i,t),e(p)}return h===F&&(h=jo(i,t)),s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof n!="function")throw new ei("Expected a function");return t=Iu(t)||0,bu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?Di(Iu(r.maxWait)||0,t):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==F&&ho(h),_=0,c=p=a=h=F},f.flush=function(){return h===F?s:o(Jo())},f}function lu(n,t){function r(){var e=arguments,u=t?t.apply(this,e):e[0],i=r.cache;return i.has(u)?i.get(u):(e=n.apply(this,e),
|
||||
r.cache=i.set(u,e)||i,e)}if(typeof n!="function"||null!=t&&typeof t!="function")throw new ei("Expected a function");return r.cache=new(lu.Cache||Pn),r}function su(n){if(typeof n!="function")throw new ei("Expected a function");return function(){var t=arguments;switch(t.length){case 0:return!n.call(this);case 1:return!n.call(this,t[0]);case 2:return!n.call(this,t[0],t[1]);case 3:return!n.call(this,t[0],t[1],t[2])}return!n.apply(this,t)}}function hu(n,t){return n===t||n!==n&&t!==t}function pu(n){return null!=n&&yu(n.length)&&!gu(n);
|
||||
}function _u(n){return xu(n)&&pu(n)}function vu(n){if(!xu(n))return false;var t=zt(n);return"[object Error]"==t||"[object DOMException]"==t||typeof n.message=="string"&&typeof n.name=="string"&&!wu(n)}function gu(n){return!!bu(n)&&(n=zt(n),"[object Function]"==n||"[object GeneratorFunction]"==n||"[object AsyncFunction]"==n||"[object Proxy]"==n)}function du(n){return typeof n=="number"&&n==Ou(n)}function yu(n){return typeof n=="number"&&-1<n&&0==n%1&&9007199254740991>=n}function bu(n){var t=typeof n;return null!=n&&("object"==t||"function"==t);
|
||||
}function xu(n){return null!=n&&typeof n=="object"}function ju(n){return typeof n=="number"||xu(n)&&"[object Number]"==zt(n)}function wu(n){return!(!xu(n)||"[object Object]"!=zt(n))&&(n=bi(n),null===n||(n=ci.call(n,"constructor")&&n.constructor,typeof n=="function"&&n instanceof n&&fi.call(n)==hi))}function mu(n){return typeof n=="string"||!af(n)&&xu(n)&&"[object String]"==zt(n)}function Au(n){return typeof n=="symbol"||xu(n)&&"[object Symbol]"==zt(n)}function ku(n){if(!n)return[];if(pu(n))return mu(n)?$(n):Mr(n);
|
||||
if(Ai&&n[Ai]){n=n[Ai]();for(var t,r=[];!(t=n.next()).done;)r.push(t.value);return r}return t=yo(n),("[object Map]"==t?L:"[object Set]"==t?D:Du)(n)}function Eu(n){return n?(n=Iu(n),n===N||n===-N?1.7976931348623157e308*(0>n?-1:1):n===n?n:0):0===n?n:0}function Ou(n){n=Eu(n);var t=n%1;return n===n?t?n-t:n:0}function Su(n){return n?gt(Ou(n),0,4294967295):0}function Iu(n){if(typeof n=="number")return n;if(Au(n))return P;if(bu(n)&&(n=typeof n.valueOf=="function"?n.valueOf():n,n=bu(n)?n+"":n),typeof n!="string")return 0===n?n:+n;
|
||||
n=n.replace(cn,"");var t=bn.test(n);return t||jn.test(n)?Fn(n.slice(2),t?2:8):yn.test(n)?P:+n}function Ru(n){return Tr(n,Uu(n))}function zu(n){return null==n?"":jr(n)}function Wu(n,t,r){return n=null==n?F:It(n,t),n===F?r:n}function Bu(n,t){return null!=n&&ke(n,t,Lt)}function Lu(n){return pu(n)?Gn(n):Ht(n)}function Uu(n){if(pu(n))n=Gn(n,true);else if(bu(n)){var t,r=Le(n),e=[];for(t in n)("constructor"!=t||!r&&ci.call(n,t))&&e.push(t);n=e}else{if(t=[],null!=n)for(r in ni(n))t.push(r);n=t}return n}function Cu(n,t){
|
||||
if(null==n)return{};var r=l(ye(n),function(n){return[n]});return t=je(t),ur(n,r,function(n,r){return t(n,r[0])})}function Du(n){return null==n?[]:I(n,Lu(n))}function Mu(n){return Nf(zu(n).toLowerCase())}function Tu(n){return(n=zu(n))&&n.replace(mn,rt).replace(Rn,"")}function $u(n,t,r){return n=zu(n),t=r?F:t,t===F?Ln.test(n)?n.match(Wn)||[]:n.match(_n)||[]:n.match(t)||[]}function Fu(n){return function(){return n}}function Nu(n){return n}function Pu(n){return Gt(typeof n=="function"?n:dt(n,1))}function Zu(n,t,r){
|
||||
var e=Lu(t),i=St(t,e);null!=r||bu(t)&&(i.length||!e.length)||(r=t,t=n,n=this,i=St(t,Lu(t)));var o=!(bu(r)&&"chain"in r&&!r.chain),f=gu(n);return u(i,function(r){var e=t[r];n[r]=e,f&&(n.prototype[r]=function(){var t=this.__chain__;if(o||t){var r=n(this.__wrapped__);return(r.__actions__=Mr(this.__actions__)).push({func:e,args:arguments,thisArg:n}),r.__chain__=t,r}return e.apply(n,s([this.value()],arguments))})}),n}function qu(){}function Vu(n){return We(n)?j($e(n)):ir(n)}function Ku(){return[]}function Gu(){
|
||||
return false}En=null==En?Zn:it.defaults(Zn.Object(),En,it.pick(Zn,Un));var Hu=En.Array,Ju=En.Date,Yu=En.Error,Qu=En.Function,Xu=En.Math,ni=En.Object,ti=En.RegExp,ri=En.String,ei=En.TypeError,ui=Hu.prototype,ii=ni.prototype,oi=En["__core-js_shared__"],fi=Qu.prototype.toString,ci=ii.hasOwnProperty,ai=0,li=function(){var n=/[^.]+$/.exec(oi&&oi.keys&&oi.keys.IE_PROTO||"");return n?"Symbol(src)_1."+n:""}(),si=ii.toString,hi=fi.call(ni),pi=Zn._,_i=ti("^"+fi.call(ci).replace(on,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),vi=Kn?En.Buffer:F,gi=En.Symbol,di=En.Uint8Array,yi=vi?vi.f:F,bi=U(ni.getPrototypeOf,ni),xi=ni.create,ji=ii.propertyIsEnumerable,wi=ui.splice,mi=gi?gi.isConcatSpreadable:F,Ai=gi?gi.iterator:F,ki=gi?gi.toStringTag:F,Ei=function(){
|
||||
try{var n=Ae(ni,"defineProperty");return n({},"",{}),n}catch(n){}}(),Oi=En.clearTimeout!==Zn.clearTimeout&&En.clearTimeout,Si=Ju&&Ju.now!==Zn.Date.now&&Ju.now,Ii=En.setTimeout!==Zn.setTimeout&&En.setTimeout,Ri=Xu.ceil,zi=Xu.floor,Wi=ni.getOwnPropertySymbols,Bi=vi?vi.isBuffer:F,Li=En.isFinite,Ui=ui.join,Ci=U(ni.keys,ni),Di=Xu.max,Mi=Xu.min,Ti=Ju.now,$i=En.parseInt,Fi=Xu.random,Ni=ui.reverse,Pi=Ae(En,"DataView"),Zi=Ae(En,"Map"),qi=Ae(En,"Promise"),Vi=Ae(En,"Set"),Ki=Ae(En,"WeakMap"),Gi=Ae(ni,"create"),Hi=Ki&&new Ki,Ji={},Yi=Fe(Pi),Qi=Fe(Zi),Xi=Fe(qi),no=Fe(Vi),to=Fe(Ki),ro=gi?gi.prototype:F,eo=ro?ro.valueOf:F,uo=ro?ro.toString:F,io=function(){
|
||||
function n(){}return function(t){return bu(t)?xi?xi(t):(n.prototype=t,t=new n,n.prototype=F,t):{}}}();On.templateSettings={escape:Q,evaluate:X,interpolate:nn,variable:"",imports:{_:On}},On.prototype=Sn.prototype,On.prototype.constructor=On,zn.prototype=io(Sn.prototype),zn.prototype.constructor=zn,Mn.prototype=io(Sn.prototype),Mn.prototype.constructor=Mn,Tn.prototype.clear=function(){this.__data__=Gi?Gi(null):{},this.size=0},Tn.prototype.delete=function(n){return n=this.has(n)&&delete this.__data__[n],
|
||||
this.size-=n?1:0,n},Tn.prototype.get=function(n){var t=this.__data__;return Gi?(n=t[n],"__lodash_hash_undefined__"===n?F:n):ci.call(t,n)?t[n]:F},Tn.prototype.has=function(n){var t=this.__data__;return Gi?t[n]!==F:ci.call(t,n)},Tn.prototype.set=function(n,t){var r=this.__data__;return this.size+=this.has(n)?0:1,r[n]=Gi&&t===F?"__lodash_hash_undefined__":t,this},Nn.prototype.clear=function(){this.__data__=[],this.size=0},Nn.prototype.delete=function(n){var t=this.__data__;return n=lt(t,n),!(0>n)&&(n==t.length-1?t.pop():wi.call(t,n,1),
|
||||
--this.size,true)},Nn.prototype.get=function(n){var t=this.__data__;return n=lt(t,n),0>n?F:t[n][1]},Nn.prototype.has=function(n){return-1<lt(this.__data__,n)},Nn.prototype.set=function(n,t){var r=this.__data__,e=lt(r,n);return 0>e?(++this.size,r.push([n,t])):r[e][1]=t,this},Pn.prototype.clear=function(){this.size=0,this.__data__={hash:new Tn,map:new(Zi||Nn),string:new Tn}},Pn.prototype.delete=function(n){return n=we(this,n).delete(n),this.size-=n?1:0,n},Pn.prototype.get=function(n){return we(this,n).get(n);
|
||||
},Pn.prototype.has=function(n){return we(this,n).has(n)},Pn.prototype.set=function(n,t){var r=we(this,n),e=r.size;return r.set(n,t),this.size+=r.size==e?0:1,this},qn.prototype.add=qn.prototype.push=function(n){return this.__data__.set(n,"__lodash_hash_undefined__"),this},qn.prototype.has=function(n){return this.__data__.has(n)},Vn.prototype.clear=function(){this.__data__=new Nn,this.size=0},Vn.prototype.delete=function(n){var t=this.__data__;return n=t.delete(n),this.size=t.size,n},Vn.prototype.get=function(n){
|
||||
return this.__data__.get(n)},Vn.prototype.has=function(n){return this.__data__.has(n)},Vn.prototype.set=function(n,t){var r=this.__data__;if(r instanceof Nn){var e=r.__data__;if(!Zi||199>e.length)return e.push([n,t]),this.size=++r.size,this;r=this.__data__=new Pn(e)}return r.set(n,t),this.size=r.size,this};var oo=Zr(Et),fo=Zr(Ot,true),co=qr(),ao=qr(true),lo=Hi?function(n,t){return Hi.set(n,t),n}:Nu,so=Ei?function(n,t){return Ei(n,"toString",{configurable:true,enumerable:false,value:Fu(t),writable:true})}:Nu,ho=Oi||function(n){
|
||||
return Zn.clearTimeout(n)},po=Vi&&1/D(new Vi([,-0]))[1]==N?function(n){return new Vi(n)}:qu,_o=Hi?function(n){return Hi.get(n)}:qu,vo=Wi?function(n){return null==n?[]:(n=ni(n),f(Wi(n),function(t){return ji.call(n,t)}))}:Ku,go=Wi?function(n){for(var t=[];n;)s(t,vo(n)),n=bi(n);return t}:Ku,yo=zt;(Pi&&"[object DataView]"!=yo(new Pi(new ArrayBuffer(1)))||Zi&&"[object Map]"!=yo(new Zi)||qi&&"[object Promise]"!=yo(qi.resolve())||Vi&&"[object Set]"!=yo(new Vi)||Ki&&"[object WeakMap]"!=yo(new Ki))&&(yo=function(n){
|
||||
var t=zt(n);if(n=(n="[object Object]"==t?n.constructor:F)?Fe(n):"")switch(n){case Yi:return"[object DataView]";case Qi:return"[object Map]";case Xi:return"[object Promise]";case no:return"[object Set]";case to:return"[object WeakMap]"}return t});var bo=oi?gu:Gu,xo=Me(lo),jo=Ii||function(n,t){return Zn.setTimeout(n,t)},wo=Me(so),mo=function(n){n=lu(n,function(n){return 500===t.size&&t.clear(),n});var t=n.cache;return n}(function(n){var t=[];return en.test(n)&&t.push(""),n.replace(un,function(n,r,e,u){
|
||||
t.push(e?u.replace(vn,"$1"):r||n)}),t}),Ao=lr(function(n,t){return _u(n)?jt(n,kt(t,1,_u,true)):[]}),ko=lr(function(n,t){var r=Ge(t);return _u(r)&&(r=F),_u(n)?jt(n,kt(t,1,_u,true),je(r,2)):[]}),Eo=lr(function(n,t){var r=Ge(t);return _u(r)&&(r=F),_u(n)?jt(n,kt(t,1,_u,true),F,r):[]}),Oo=lr(function(n){var t=l(n,Sr);return t.length&&t[0]===n[0]?Ut(t):[]}),So=lr(function(n){var t=Ge(n),r=l(n,Sr);return t===Ge(r)?t=F:r.pop(),r.length&&r[0]===n[0]?Ut(r,je(t,2)):[]}),Io=lr(function(n){var t=Ge(n),r=l(n,Sr);return(t=typeof t=="function"?t:F)&&r.pop(),
|
||||
r.length&&r[0]===n[0]?Ut(r,F,t):[]}),Ro=lr(He),zo=ge(function(n,t){var r=null==n?0:n.length,e=vt(n,t);return fr(n,l(t,function(n){return Re(n,r)?+n:n}).sort(Ur)),e}),Wo=lr(function(n){return wr(kt(n,1,_u,true))}),Bo=lr(function(n){var t=Ge(n);return _u(t)&&(t=F),wr(kt(n,1,_u,true),je(t,2))}),Lo=lr(function(n){var t=Ge(n),t=typeof t=="function"?t:F;return wr(kt(n,1,_u,true),F,t)}),Uo=lr(function(n,t){return _u(n)?jt(n,t):[]}),Co=lr(function(n){return Er(f(n,_u))}),Do=lr(function(n){var t=Ge(n);return _u(t)&&(t=F),
|
||||
Er(f(n,_u),je(t,2))}),Mo=lr(function(n){var t=Ge(n),t=typeof t=="function"?t:F;return Er(f(n,_u),F,t)}),To=lr(Ye),$o=lr(function(n){var t=n.length,t=1<t?n[t-1]:F,t=typeof t=="function"?(n.pop(),t):F;return Qe(n,t)}),Fo=ge(function(n){function t(t){return vt(t,n)}var r=n.length,e=r?n[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof Mn&&Re(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:nu,args:[t],thisArg:F}),new zn(u,this.__chain__).thru(function(n){return r&&!n.length&&n.push(F),
|
||||
n})):this.thru(t)}),No=Nr(function(n,t,r){ci.call(n,r)?++n[r]:_t(n,r,1)}),Po=Yr(Ze),Zo=Yr(qe),qo=Nr(function(n,t,r){ci.call(n,r)?n[r].push(t):_t(n,r,[t])}),Vo=lr(function(n,t,e){var u=-1,i=typeof t=="function",o=pu(n)?Hu(n.length):[];return oo(n,function(n){o[++u]=i?r(t,n,e):Dt(n,t,e)}),o}),Ko=Nr(function(n,t,r){_t(n,r,t)}),Go=Nr(function(n,t,r){n[r?0:1].push(t)},function(){return[[],[]]}),Ho=lr(function(n,t){if(null==n)return[];var r=t.length;return 1<r&&ze(n,t[0],t[1])?t=[]:2<r&&ze(t[0],t[1],t[2])&&(t=[t[0]]),
|
||||
rr(n,kt(t,1),[])}),Jo=Si||function(){return Zn.Date.now()},Yo=lr(function(n,t,r){var e=1;if(r.length)var u=C(r,xe(Yo)),e=32|e;return le(n,e,t,r,u)}),Qo=lr(function(n,t,r){var e=3;if(r.length)var u=C(r,xe(Qo)),e=32|e;return le(t,e,n,r,u)}),Xo=lr(function(n,t){return xt(n,1,t)}),nf=lr(function(n,t,r){return xt(n,Iu(t)||0,r)});lu.Cache=Pn;var tf=lr(function(n,t){t=1==t.length&&af(t[0])?l(t[0],S(je())):l(kt(t,1),S(je()));var e=t.length;return lr(function(u){for(var i=-1,o=Mi(u.length,e);++i<o;)u[i]=t[i].call(this,u[i]);
|
||||
return r(n,this,u)})}),rf=lr(function(n,t){return le(n,32,F,t,C(t,xe(rf)))}),ef=lr(function(n,t){return le(n,64,F,t,C(t,xe(ef)))}),uf=ge(function(n,t){return le(n,256,F,F,F,t)}),of=oe(Wt),ff=oe(function(n,t){return n>=t}),cf=Mt(function(){return arguments}())?Mt:function(n){return xu(n)&&ci.call(n,"callee")&&!ji.call(n,"callee")},af=Hu.isArray,lf=Hn?S(Hn):Tt,sf=Bi||Gu,hf=Jn?S(Jn):$t,pf=Yn?S(Yn):Nt,_f=Qn?S(Qn):qt,vf=Xn?S(Xn):Vt,gf=nt?S(nt):Kt,df=oe(Jt),yf=oe(function(n,t){return n<=t}),bf=Pr(function(n,t){
|
||||
if(Le(t)||pu(t))Tr(t,Lu(t),n);else for(var r in t)ci.call(t,r)&&at(n,r,t[r])}),xf=Pr(function(n,t){Tr(t,Uu(t),n)}),jf=Pr(function(n,t,r,e){Tr(t,Uu(t),n,e)}),wf=Pr(function(n,t,r,e){Tr(t,Lu(t),n,e)}),mf=ge(vt),Af=lr(function(n){return n.push(F,se),r(jf,F,n)}),kf=lr(function(n){return n.push(F,he),r(Rf,F,n)}),Ef=ne(function(n,t,r){n[t]=r},Fu(Nu)),Of=ne(function(n,t,r){ci.call(n,t)?n[t].push(r):n[t]=[r]},je),Sf=lr(Dt),If=Pr(function(n,t,r){nr(n,t,r)}),Rf=Pr(function(n,t,r,e){nr(n,t,r,e)}),zf=ge(function(n,t){
|
||||
var r={};if(null==n)return r;var e=false;t=l(t,function(t){return t=Rr(t,n),e||(e=1<t.length),t}),Tr(n,ye(n),r),e&&(r=dt(r,7,pe));for(var u=t.length;u--;)mr(r,t[u]);return r}),Wf=ge(function(n,t){return null==n?{}:er(n,t)}),Bf=ae(Lu),Lf=ae(Uu),Uf=Gr(function(n,t,r){return t=t.toLowerCase(),n+(r?Mu(t):t)}),Cf=Gr(function(n,t,r){return n+(r?"-":"")+t.toLowerCase()}),Df=Gr(function(n,t,r){return n+(r?" ":"")+t.toLowerCase()}),Mf=Kr("toLowerCase"),Tf=Gr(function(n,t,r){return n+(r?"_":"")+t.toLowerCase();
|
||||
}),$f=Gr(function(n,t,r){return n+(r?" ":"")+Nf(t)}),Ff=Gr(function(n,t,r){return n+(r?" ":"")+t.toUpperCase()}),Nf=Kr("toUpperCase"),Pf=lr(function(n,t){try{return r(n,F,t)}catch(n){return vu(n)?n:new Yu(n)}}),Zf=ge(function(n,t){return u(t,function(t){t=$e(t),_t(n,t,Yo(n[t],n))}),n}),qf=Qr(),Vf=Qr(true),Kf=lr(function(n,t){return function(r){return Dt(r,n,t)}}),Gf=lr(function(n,t){return function(r){return Dt(n,r,t)}}),Hf=re(l),Jf=re(o),Yf=re(_),Qf=ie(),Xf=ie(true),nc=te(function(n,t){return n+t},0),tc=ce("ceil"),rc=te(function(n,t){
|
||||
return n/t},1),ec=ce("floor"),uc=te(function(n,t){return n*t},1),ic=ce("round"),oc=te(function(n,t){return n-t},0);return On.after=function(n,t){if(typeof t!="function")throw new ei("Expected a function");return n=Ou(n),function(){if(1>--n)return t.apply(this,arguments)}},On.ary=iu,On.assign=bf,On.assignIn=xf,On.assignInWith=jf,On.assignWith=wf,On.at=mf,On.before=ou,On.bind=Yo,On.bindAll=Zf,On.bindKey=Qo,On.castArray=function(){if(!arguments.length)return[];var n=arguments[0];return af(n)?n:[n]},
|
||||
On.chain=Xe,On.chunk=function(n,t,r){if(t=(r?ze(n,t,r):t===F)?1:Di(Ou(t),0),r=null==n?0:n.length,!r||1>t)return[];for(var e=0,u=0,i=Hu(Ri(r/t));e<r;)i[u++]=vr(n,e,e+=t);return i},On.compact=function(n){for(var t=-1,r=null==n?0:n.length,e=0,u=[];++t<r;){var i=n[t];i&&(u[e++]=i)}return u},On.concat=function(){var n=arguments.length;if(!n)return[];for(var t=Hu(n-1),r=arguments[0];n--;)t[n-1]=arguments[n];return s(af(r)?Mr(r):[r],kt(t,1))},On.cond=function(n){var t=null==n?0:n.length,e=je();return n=t?l(n,function(n){
|
||||
if("function"!=typeof n[1])throw new ei("Expected a function");return[e(n[0]),n[1]]}):[],lr(function(e){for(var u=-1;++u<t;){var i=n[u];if(r(i[0],this,e))return r(i[1],this,e)}})},On.conforms=function(n){return yt(dt(n,1))},On.constant=Fu,On.countBy=No,On.create=function(n,t){var r=io(n);return null==t?r:ht(r,t)},On.curry=fu,On.curryRight=cu,On.debounce=au,On.defaults=Af,On.defaultsDeep=kf,On.defer=Xo,On.delay=nf,On.difference=Ao,On.differenceBy=ko,On.differenceWith=Eo,On.drop=function(n,t,r){var e=null==n?0:n.length;
|
||||
return e?(t=r||t===F?1:Ou(t),vr(n,0>t?0:t,e)):[]},On.dropRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===F?1:Ou(t),t=e-t,vr(n,0,0>t?0:t)):[]},On.dropRightWhile=function(n,t){return n&&n.length?Ar(n,je(t,3),true,true):[]},On.dropWhile=function(n,t){return n&&n.length?Ar(n,je(t,3),true):[]},On.fill=function(n,t,r,e){var u=null==n?0:n.length;if(!u)return[];for(r&&typeof r!="number"&&ze(n,t,r)&&(r=0,e=u),u=n.length,r=Ou(r),0>r&&(r=-r>u?0:u+r),e=e===F||e>u?u:Ou(e),0>e&&(e+=u),e=r>e?0:Su(e);r<e;)n[r++]=t;
|
||||
return n},On.filter=function(n,t){return(af(n)?f:At)(n,je(t,3))},On.flatMap=function(n,t){return kt(uu(n,t),1)},On.flatMapDeep=function(n,t){return kt(uu(n,t),N)},On.flatMapDepth=function(n,t,r){return r=r===F?1:Ou(r),kt(uu(n,t),r)},On.flatten=Ve,On.flattenDeep=function(n){return(null==n?0:n.length)?kt(n,N):[]},On.flattenDepth=function(n,t){return null!=n&&n.length?(t=t===F?1:Ou(t),kt(n,t)):[]},On.flip=function(n){return le(n,512)},On.flow=qf,On.flowRight=Vf,On.fromPairs=function(n){for(var t=-1,r=null==n?0:n.length,e={};++t<r;){
|
||||
var u=n[t];e[u[0]]=u[1]}return e},On.functions=function(n){return null==n?[]:St(n,Lu(n))},On.functionsIn=function(n){return null==n?[]:St(n,Uu(n))},On.groupBy=qo,On.initial=function(n){return(null==n?0:n.length)?vr(n,0,-1):[]},On.intersection=Oo,On.intersectionBy=So,On.intersectionWith=Io,On.invert=Ef,On.invertBy=Of,On.invokeMap=Vo,On.iteratee=Pu,On.keyBy=Ko,On.keys=Lu,On.keysIn=Uu,On.map=uu,On.mapKeys=function(n,t){var r={};return t=je(t,3),Et(n,function(n,e,u){_t(r,t(n,e,u),n)}),r},On.mapValues=function(n,t){
|
||||
var r={};return t=je(t,3),Et(n,function(n,e,u){_t(r,e,t(n,e,u))}),r},On.matches=function(n){return Qt(dt(n,1))},On.matchesProperty=function(n,t){return Xt(n,dt(t,1))},On.memoize=lu,On.merge=If,On.mergeWith=Rf,On.method=Kf,On.methodOf=Gf,On.mixin=Zu,On.negate=su,On.nthArg=function(n){return n=Ou(n),lr(function(t){return tr(t,n)})},On.omit=zf,On.omitBy=function(n,t){return Cu(n,su(je(t)))},On.once=function(n){return ou(2,n)},On.orderBy=function(n,t,r,e){return null==n?[]:(af(t)||(t=null==t?[]:[t]),
|
||||
r=e?F:r,af(r)||(r=null==r?[]:[r]),rr(n,t,r))},On.over=Hf,On.overArgs=tf,On.overEvery=Jf,On.overSome=Yf,On.partial=rf,On.partialRight=ef,On.partition=Go,On.pick=Wf,On.pickBy=Cu,On.property=Vu,On.propertyOf=function(n){return function(t){return null==n?F:It(n,t)}},On.pull=Ro,On.pullAll=He,On.pullAllBy=function(n,t,r){return n&&n.length&&t&&t.length?or(n,t,je(r,2)):n},On.pullAllWith=function(n,t,r){return n&&n.length&&t&&t.length?or(n,t,F,r):n},On.pullAt=zo,On.range=Qf,On.rangeRight=Xf,On.rearg=uf,On.reject=function(n,t){
|
||||
return(af(n)?f:At)(n,su(je(t,3)))},On.remove=function(n,t){var r=[];if(!n||!n.length)return r;var e=-1,u=[],i=n.length;for(t=je(t,3);++e<i;){var o=n[e];t(o,e,n)&&(r.push(o),u.push(e))}return fr(n,u),r},On.rest=function(n,t){if(typeof n!="function")throw new ei("Expected a function");return t=t===F?t:Ou(t),lr(n,t)},On.reverse=Je,On.sampleSize=function(n,t,r){return t=(r?ze(n,t,r):t===F)?1:Ou(t),(af(n)?ot:hr)(n,t)},On.set=function(n,t,r){return null==n?n:pr(n,t,r)},On.setWith=function(n,t,r,e){return e=typeof e=="function"?e:F,
|
||||
null==n?n:pr(n,t,r,e)},On.shuffle=function(n){return(af(n)?ft:_r)(n)},On.slice=function(n,t,r){var e=null==n?0:n.length;return e?(r&&typeof r!="number"&&ze(n,t,r)?(t=0,r=e):(t=null==t?0:Ou(t),r=r===F?e:Ou(r)),vr(n,t,r)):[]},On.sortBy=Ho,On.sortedUniq=function(n){return n&&n.length?br(n):[]},On.sortedUniqBy=function(n,t){return n&&n.length?br(n,je(t,2)):[]},On.split=function(n,t,r){return r&&typeof r!="number"&&ze(n,t,r)&&(t=r=F),r=r===F?4294967295:r>>>0,r?(n=zu(n))&&(typeof t=="string"||null!=t&&!_f(t))&&(t=jr(t),
|
||||
!t&&Bn.test(n))?zr($(n),0,r):n.split(t,r):[]},On.spread=function(n,t){if(typeof n!="function")throw new ei("Expected a function");return t=null==t?0:Di(Ou(t),0),lr(function(e){var u=e[t];return e=zr(e,0,t),u&&s(e,u),r(n,this,e)})},On.tail=function(n){var t=null==n?0:n.length;return t?vr(n,1,t):[]},On.take=function(n,t,r){return n&&n.length?(t=r||t===F?1:Ou(t),vr(n,0,0>t?0:t)):[]},On.takeRight=function(n,t,r){var e=null==n?0:n.length;return e?(t=r||t===F?1:Ou(t),t=e-t,vr(n,0>t?0:t,e)):[]},On.takeRightWhile=function(n,t){
|
||||
return n&&n.length?Ar(n,je(t,3),false,true):[]},On.takeWhile=function(n,t){return n&&n.length?Ar(n,je(t,3)):[]},On.tap=function(n,t){return t(n),n},On.throttle=function(n,t,r){var e=true,u=true;if(typeof n!="function")throw new ei("Expected a function");return bu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),au(n,t,{leading:e,maxWait:t,trailing:u})},On.thru=nu,On.toArray=ku,On.toPairs=Bf,On.toPairsIn=Lf,On.toPath=function(n){return af(n)?l(n,$e):Au(n)?[n]:Mr(mo(zu(n)))},On.toPlainObject=Ru,
|
||||
On.transform=function(n,t,r){var e=af(n),i=e||sf(n)||gf(n);if(t=je(t,4),null==r){var o=n&&n.constructor;r=i?e?new o:[]:bu(n)&&gu(o)?io(bi(n)):{}}return(i?u:Et)(n,function(n,e,u){return t(r,n,e,u)}),r},On.unary=function(n){return iu(n,1)},On.union=Wo,On.unionBy=Bo,On.unionWith=Lo,On.uniq=function(n){return n&&n.length?wr(n):[]},On.uniqBy=function(n,t){return n&&n.length?wr(n,je(t,2)):[]},On.uniqWith=function(n,t){return t=typeof t=="function"?t:F,n&&n.length?wr(n,F,t):[]},On.unset=function(n,t){return null==n||mr(n,t);
|
||||
},On.unzip=Ye,On.unzipWith=Qe,On.update=function(n,t,r){return null==n?n:pr(n,t,Ir(r)(It(n,t)),void 0)},On.updateWith=function(n,t,r,e){return e=typeof e=="function"?e:F,null!=n&&(n=pr(n,t,Ir(r)(It(n,t)),e)),n},On.values=Du,On.valuesIn=function(n){return null==n?[]:I(n,Uu(n))},On.without=Uo,On.words=$u,On.wrap=function(n,t){return rf(Ir(t),n)},On.xor=Co,On.xorBy=Do,On.xorWith=Mo,On.zip=To,On.zipObject=function(n,t){return Or(n||[],t||[],at)},On.zipObjectDeep=function(n,t){return Or(n||[],t||[],pr);
|
||||
},On.zipWith=$o,On.entries=Bf,On.entriesIn=Lf,On.extend=xf,On.extendWith=jf,Zu(On,On),On.add=nc,On.attempt=Pf,On.camelCase=Uf,On.capitalize=Mu,On.ceil=tc,On.clamp=function(n,t,r){return r===F&&(r=t,t=F),r!==F&&(r=Iu(r),r=r===r?r:0),t!==F&&(t=Iu(t),t=t===t?t:0),gt(Iu(n),t,r)},On.clone=function(n){return dt(n,4)},On.cloneDeep=function(n){return dt(n,5)},On.cloneDeepWith=function(n,t){return t=typeof t=="function"?t:F,dt(n,5,t)},On.cloneWith=function(n,t){return t=typeof t=="function"?t:F,dt(n,4,t)},
|
||||
On.conformsTo=function(n,t){return null==t||bt(n,t,Lu(t))},On.deburr=Tu,On.defaultTo=function(n,t){return null==n||n!==n?t:n},On.divide=rc,On.endsWith=function(n,t,r){n=zu(n),t=jr(t);var e=n.length,e=r=r===F?e:gt(Ou(r),0,e);return r-=t.length,0<=r&&n.slice(r,e)==t},On.eq=hu,On.escape=function(n){return(n=zu(n))&&Y.test(n)?n.replace(H,et):n},On.escapeRegExp=function(n){return(n=zu(n))&&fn.test(n)?n.replace(on,"\\$&"):n},On.every=function(n,t,r){var e=af(n)?o:wt;return r&&ze(n,t,r)&&(t=F),e(n,je(t,3));
|
||||
},On.find=Po,On.findIndex=Ze,On.findKey=function(n,t){return v(n,je(t,3),Et)},On.findLast=Zo,On.findLastIndex=qe,On.findLastKey=function(n,t){return v(n,je(t,3),Ot)},On.floor=ec,On.forEach=ru,On.forEachRight=eu,On.forIn=function(n,t){return null==n?n:co(n,je(t,3),Uu)},On.forInRight=function(n,t){return null==n?n:ao(n,je(t,3),Uu)},On.forOwn=function(n,t){return n&&Et(n,je(t,3))},On.forOwnRight=function(n,t){return n&&Ot(n,je(t,3))},On.get=Wu,On.gt=of,On.gte=ff,On.has=function(n,t){return null!=n&&ke(n,t,Bt);
|
||||
},On.hasIn=Bu,On.head=Ke,On.identity=Nu,On.includes=function(n,t,r,e){return n=pu(n)?n:Du(n),r=r&&!e?Ou(r):0,e=n.length,0>r&&(r=Di(e+r,0)),mu(n)?r<=e&&-1<n.indexOf(t,r):!!e&&-1<d(n,t,r)},On.indexOf=function(n,t,r){var e=null==n?0:n.length;return e?(r=null==r?0:Ou(r),0>r&&(r=Di(e+r,0)),d(n,t,r)):-1},On.inRange=function(n,t,r){return t=Eu(t),r===F?(r=t,t=0):r=Eu(r),n=Iu(n),n>=Mi(t,r)&&n<Di(t,r)},On.invoke=Sf,On.isArguments=cf,On.isArray=af,On.isArrayBuffer=lf,On.isArrayLike=pu,On.isArrayLikeObject=_u,
|
||||
On.isBoolean=function(n){return true===n||false===n||xu(n)&&"[object Boolean]"==zt(n)},On.isBuffer=sf,On.isDate=hf,On.isElement=function(n){return xu(n)&&1===n.nodeType&&!wu(n)},On.isEmpty=function(n){if(null==n)return true;if(pu(n)&&(af(n)||typeof n=="string"||typeof n.splice=="function"||sf(n)||gf(n)||cf(n)))return!n.length;var t=yo(n);if("[object Map]"==t||"[object Set]"==t)return!n.size;if(Le(n))return!Ht(n).length;for(var r in n)if(ci.call(n,r))return false;return true},On.isEqual=function(n,t){return Ft(n,t);
|
||||
},On.isEqualWith=function(n,t,r){var e=(r=typeof r=="function"?r:F)?r(n,t):F;return e===F?Ft(n,t,F,r):!!e},On.isError=vu,On.isFinite=function(n){return typeof n=="number"&&Li(n)},On.isFunction=gu,On.isInteger=du,On.isLength=yu,On.isMap=pf,On.isMatch=function(n,t){return n===t||Pt(n,t,me(t))},On.isMatchWith=function(n,t,r){return r=typeof r=="function"?r:F,Pt(n,t,me(t),r)},On.isNaN=function(n){return ju(n)&&n!=+n},On.isNative=function(n){if(bo(n))throw new Yu("Unsupported core-js use. Try https://npms.io/search?q=ponyfill.");
|
||||
return Zt(n)},On.isNil=function(n){return null==n},On.isNull=function(n){return null===n},On.isNumber=ju,On.isObject=bu,On.isObjectLike=xu,On.isPlainObject=wu,On.isRegExp=_f,On.isSafeInteger=function(n){return du(n)&&-9007199254740991<=n&&9007199254740991>=n},On.isSet=vf,On.isString=mu,On.isSymbol=Au,On.isTypedArray=gf,On.isUndefined=function(n){return n===F},On.isWeakMap=function(n){return xu(n)&&"[object WeakMap]"==yo(n)},On.isWeakSet=function(n){return xu(n)&&"[object WeakSet]"==zt(n)},On.join=function(n,t){
|
||||
return null==n?"":Ui.call(n,t)},On.kebabCase=Cf,On.last=Ge,On.lastIndexOf=function(n,t,r){var e=null==n?0:n.length;if(!e)return-1;var u=e;if(r!==F&&(u=Ou(r),u=0>u?Di(e+u,0):Mi(u,e-1)),t===t){for(r=u+1;r--&&n[r]!==t;);n=r}else n=g(n,b,u,true);return n},On.lowerCase=Df,On.lowerFirst=Mf,On.lt=df,On.lte=yf,On.max=function(n){return n&&n.length?mt(n,Nu,Wt):F},On.maxBy=function(n,t){return n&&n.length?mt(n,je(t,2),Wt):F},On.mean=function(n){return x(n,Nu)},On.meanBy=function(n,t){return x(n,je(t,2))},On.min=function(n){
|
||||
return n&&n.length?mt(n,Nu,Jt):F},On.minBy=function(n,t){return n&&n.length?mt(n,je(t,2),Jt):F},On.stubArray=Ku,On.stubFalse=Gu,On.stubObject=function(){return{}},On.stubString=function(){return""},On.stubTrue=function(){return true},On.multiply=uc,On.nth=function(n,t){return n&&n.length?tr(n,Ou(t)):F},On.noConflict=function(){return Zn._===this&&(Zn._=pi),this},On.noop=qu,On.now=Jo,On.pad=function(n,t,r){n=zu(n);var e=(t=Ou(t))?T(n):0;return!t||e>=t?n:(t=(t-e)/2,ee(zi(t),r)+n+ee(Ri(t),r))},On.padEnd=function(n,t,r){
|
||||
n=zu(n);var e=(t=Ou(t))?T(n):0;return t&&e<t?n+ee(t-e,r):n},On.padStart=function(n,t,r){n=zu(n);var e=(t=Ou(t))?T(n):0;return t&&e<t?ee(t-e,r)+n:n},On.parseInt=function(n,t,r){return r||null==t?t=0:t&&(t=+t),$i(zu(n).replace(an,""),t||0)},On.random=function(n,t,r){if(r&&typeof r!="boolean"&&ze(n,t,r)&&(t=r=F),r===F&&(typeof t=="boolean"?(r=t,t=F):typeof n=="boolean"&&(r=n,n=F)),n===F&&t===F?(n=0,t=1):(n=Eu(n),t===F?(t=n,n=0):t=Eu(t)),n>t){var e=n;n=t,t=e}return r||n%1||t%1?(r=Fi(),Mi(n+r*(t-n+$n("1e-"+((r+"").length-1))),t)):cr(n,t);
|
||||
},On.reduce=function(n,t,r){var e=af(n)?h:m,u=3>arguments.length;return e(n,je(t,4),r,u,oo)},On.reduceRight=function(n,t,r){var e=af(n)?p:m,u=3>arguments.length;return e(n,je(t,4),r,u,fo)},On.repeat=function(n,t,r){return t=(r?ze(n,t,r):t===F)?1:Ou(t),ar(zu(n),t)},On.replace=function(){var n=arguments,t=zu(n[0]);return 3>n.length?t:t.replace(n[1],n[2])},On.result=function(n,t,r){t=Rr(t,n);var e=-1,u=t.length;for(u||(u=1,n=F);++e<u;){var i=null==n?F:n[$e(t[e])];i===F&&(e=u,i=r),n=gu(i)?i.call(n):i;
|
||||
}return n},On.round=ic,On.runInContext=w,On.sample=function(n){return(af(n)?tt:sr)(n)},On.size=function(n){if(null==n)return 0;if(pu(n))return mu(n)?T(n):n.length;var t=yo(n);return"[object Map]"==t||"[object Set]"==t?n.size:Ht(n).length},On.snakeCase=Tf,On.some=function(n,t,r){var e=af(n)?_:gr;return r&&ze(n,t,r)&&(t=F),e(n,je(t,3))},On.sortedIndex=function(n,t){return dr(n,t)},On.sortedIndexBy=function(n,t,r){return yr(n,t,je(r,2))},On.sortedIndexOf=function(n,t){var r=null==n?0:n.length;if(r){
|
||||
var e=dr(n,t);if(e<r&&hu(n[e],t))return e}return-1},On.sortedLastIndex=function(n,t){return dr(n,t,true)},On.sortedLastIndexBy=function(n,t,r){return yr(n,t,je(r,2),true)},On.sortedLastIndexOf=function(n,t){if(null==n?0:n.length){var r=dr(n,t,true)-1;if(hu(n[r],t))return r}return-1},On.startCase=$f,On.startsWith=function(n,t,r){return n=zu(n),r=null==r?0:gt(Ou(r),0,n.length),t=jr(t),n.slice(r,r+t.length)==t},On.subtract=oc,On.sum=function(n){return n&&n.length?k(n,Nu):0},On.sumBy=function(n,t){return n&&n.length?k(n,je(t,2)):0;
|
||||
},On.template=function(n,t,r){var e=On.templateSettings;r&&ze(n,t,r)&&(t=F),n=zu(n),t=jf({},t,e,se),r=jf({},t.imports,e.imports,se);var u,i,o=Lu(r),f=I(r,o),c=0;r=t.interpolate||An;var a="__p+='";r=ti((t.escape||An).source+"|"+r.source+"|"+(r===nn?gn:An).source+"|"+(t.evaluate||An).source+"|$","g");var l="sourceURL"in t?"//# sourceURL="+t.sourceURL+"\n":"";if(n.replace(r,function(t,r,e,o,f,l){return e||(e=o),a+=n.slice(c,l).replace(kn,B),r&&(u=true,a+="'+__e("+r+")+'"),f&&(i=true,a+="';"+f+";\n__p+='"),
|
||||
e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+t.length,t}),a+="';",(t=t.variable)||(a="with(obj){"+a+"}"),a=(i?a.replace(q,""):a).replace(V,"$1").replace(K,"$1;"),a="function("+(t||"obj")+"){"+(t?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",t=Pf(function(){return Qu(o,l+"return "+a).apply(F,f)}),t.source=a,vu(t))throw t;return t},On.times=function(n,t){if(n=Ou(n),1>n||9007199254740991<n)return[];
|
||||
var r=4294967295,e=Mi(n,4294967295);for(t=je(t),n-=4294967295,e=E(e,t);++r<n;)t(r);return e},On.toFinite=Eu,On.toInteger=Ou,On.toLength=Su,On.toLower=function(n){return zu(n).toLowerCase()},On.toNumber=Iu,On.toSafeInteger=function(n){return n?gt(Ou(n),-9007199254740991,9007199254740991):0===n?n:0},On.toString=zu,On.toUpper=function(n){return zu(n).toUpperCase()},On.trim=function(n,t,r){return(n=zu(n))&&(r||t===F)?n.replace(cn,""):n&&(t=jr(t))?(n=$(n),r=$(t),t=z(n,r),r=W(n,r)+1,zr(n,t,r).join("")):n;
|
||||
},On.trimEnd=function(n,t,r){return(n=zu(n))&&(r||t===F)?n.replace(ln,""):n&&(t=jr(t))?(n=$(n),t=W(n,$(t))+1,zr(n,0,t).join("")):n},On.trimStart=function(n,t,r){return(n=zu(n))&&(r||t===F)?n.replace(an,""):n&&(t=jr(t))?(n=$(n),t=z(n,$(t)),zr(n,t).join("")):n},On.truncate=function(n,t){var r=30,e="...";if(bu(t))var u="separator"in t?t.separator:u,r="length"in t?Ou(t.length):r,e="omission"in t?jr(t.omission):e;n=zu(n);var i=n.length;if(Bn.test(n))var o=$(n),i=o.length;if(r>=i)return n;if(i=r-T(e),1>i)return e;
|
||||
if(r=o?zr(o,0,i).join(""):n.slice(0,i),u===F)return r+e;if(o&&(i+=r.length-i),_f(u)){if(n.slice(i).search(u)){var f=r;for(u.global||(u=ti(u.source,zu(dn.exec(u))+"g")),u.lastIndex=0;o=u.exec(f);)var c=o.index;r=r.slice(0,c===F?i:c)}}else n.indexOf(jr(u),i)!=i&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},On.unescape=function(n){return(n=zu(n))&&J.test(n)?n.replace(G,ut):n},On.uniqueId=function(n){var t=++ai;return zu(n)+t},On.upperCase=Ff,On.upperFirst=Nf,On.each=ru,On.eachRight=eu,On.first=Ke,
|
||||
Zu(On,function(){var n={};return Et(On,function(t,r){ci.call(On.prototype,r)||(n[r]=t)}),n}(),{chain:false}),On.VERSION="4.17.4",u("bind bindKey curry curryRight partial partialRight".split(" "),function(n){On[n].placeholder=On}),u(["drop","take"],function(n,t){Mn.prototype[n]=function(r){r=r===F?1:Di(Ou(r),0);var e=this.__filtered__&&!t?new Mn(this):this.clone();return e.__filtered__?e.__takeCount__=Mi(r,e.__takeCount__):e.__views__.push({size:Mi(r,4294967295),type:n+(0>e.__dir__?"Right":"")}),e},Mn.prototype[n+"Right"]=function(t){
|
||||
return this.reverse()[n](t).reverse()}}),u(["filter","map","takeWhile"],function(n,t){var r=t+1,e=1==r||3==r;Mn.prototype[n]=function(n){var t=this.clone();return t.__iteratees__.push({iteratee:je(n,3),type:r}),t.__filtered__=t.__filtered__||e,t}}),u(["head","last"],function(n,t){var r="take"+(t?"Right":"");Mn.prototype[n]=function(){return this[r](1).value()[0]}}),u(["initial","tail"],function(n,t){var r="drop"+(t?"":"Right");Mn.prototype[n]=function(){return this.__filtered__?new Mn(this):this[r](1);
|
||||
}}),Mn.prototype.compact=function(){return this.filter(Nu)},Mn.prototype.find=function(n){return this.filter(n).head()},Mn.prototype.findLast=function(n){return this.reverse().find(n)},Mn.prototype.invokeMap=lr(function(n,t){return typeof n=="function"?new Mn(this):this.map(function(r){return Dt(r,n,t)})}),Mn.prototype.reject=function(n){return this.filter(su(je(n)))},Mn.prototype.slice=function(n,t){n=Ou(n);var r=this;return r.__filtered__&&(0<n||0>t)?new Mn(r):(0>n?r=r.takeRight(-n):n&&(r=r.drop(n)),
|
||||
t!==F&&(t=Ou(t),r=0>t?r.dropRight(-t):r.take(t-n)),r)},Mn.prototype.takeRightWhile=function(n){return this.reverse().takeWhile(n).reverse()},Mn.prototype.toArray=function(){return this.take(4294967295)},Et(Mn.prototype,function(n,t){var r=/^(?:filter|find|map|reject)|While$/.test(t),e=/^(?:head|last)$/.test(t),u=On[e?"take"+("last"==t?"Right":""):t],i=e||/^find/.test(t);u&&(On.prototype[t]=function(){function t(n){return n=u.apply(On,s([n],f)),e&&h?n[0]:n}var o=this.__wrapped__,f=e?[1]:arguments,c=o instanceof Mn,a=f[0],l=c||af(o);
|
||||
l&&r&&typeof a=="function"&&1!=a.length&&(c=l=false);var h=this.__chain__,p=!!this.__actions__.length,a=i&&!h,c=c&&!p;return!i&&l?(o=c?o:new Mn(this),o=n.apply(o,f),o.__actions__.push({func:nu,args:[t],thisArg:F}),new zn(o,h)):a&&c?n.apply(this,f):(o=this.thru(t),a?e?o.value()[0]:o.value():o)})}),u("pop push shift sort splice unshift".split(" "),function(n){var t=ui[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|shift)$/.test(n);On.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){
|
||||
var u=this.value();return t.apply(af(u)?u:[],n)}return this[r](function(r){return t.apply(af(r)?r:[],n)})}}),Et(Mn.prototype,function(n,t){var r=On[t];if(r){var e=r.name+"";(Ji[e]||(Ji[e]=[])).push({name:t,func:r})}}),Ji[Xr(F,2).name]=[{name:"wrapper",func:F}],Mn.prototype.clone=function(){var n=new Mn(this.__wrapped__);return n.__actions__=Mr(this.__actions__),n.__dir__=this.__dir__,n.__filtered__=this.__filtered__,n.__iteratees__=Mr(this.__iteratees__),n.__takeCount__=this.__takeCount__,n.__views__=Mr(this.__views__),
|
||||
n},Mn.prototype.reverse=function(){if(this.__filtered__){var n=new Mn(this);n.__dir__=-1,n.__filtered__=true}else n=this.clone(),n.__dir__*=-1;return n},Mn.prototype.value=function(){var n,t=this.__wrapped__.value(),r=this.__dir__,e=af(t),u=0>r,i=e?t.length:0;n=i;for(var o=this.__views__,f=0,c=-1,a=o.length;++c<a;){var l=o[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":n-=s;break;case"take":n=Mi(n,f+s);break;case"takeRight":f=Di(f,n-s)}}if(n={start:f,end:n},o=n.start,f=n.end,n=f-o,
|
||||
o=u?f:o-1,f=this.__iteratees__,c=f.length,a=0,l=Mi(n,this.__takeCount__),!e||!u&&i==n&&l==n)return kr(t,this.__actions__);e=[];n:for(;n--&&a<l;){for(o+=r,u=-1,i=t[o];++u<c;){var h=f[u],s=h.type,h=(0,h.iteratee)(i);if(2==s)i=h;else if(!h){if(1==s)continue n;break n}}e[a++]=i}return e},On.prototype.at=Fo,On.prototype.chain=function(){return Xe(this)},On.prototype.commit=function(){return new zn(this.value(),this.__chain__)},On.prototype.next=function(){this.__values__===F&&(this.__values__=ku(this.value()));
|
||||
var n=this.__index__>=this.__values__.length;return{done:n,value:n?F:this.__values__[this.__index__++]}},On.prototype.plant=function(n){for(var t,r=this;r instanceof Sn;){var e=Pe(r);e.__index__=0,e.__values__=F,t?u.__wrapped__=e:t=e;var u=e,r=r.__wrapped__}return u.__wrapped__=n,t},On.prototype.reverse=function(){var n=this.__wrapped__;return n instanceof Mn?(this.__actions__.length&&(n=new Mn(this)),n=n.reverse(),n.__actions__.push({func:nu,args:[Je],thisArg:F}),new zn(n,this.__chain__)):this.thru(Je);
|
||||
},On.prototype.toJSON=On.prototype.valueOf=On.prototype.value=function(){return kr(this.__wrapped__,this.__actions__)},On.prototype.first=On.prototype.head,Ai&&(On.prototype[Ai]=tu),On}();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Zn._=it, define(function(){return it})):Vn?((Vn.exports=it)._=it,qn._=it):Zn._=it}).call(this);
|
||||
10947
_static/js/vue.js
Normal file
10947
_static/js/vue.js
Normal file
File diff suppressed because it is too large
Load diff
6
requirements.txt
Normal file
6
requirements.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# oTree-may-overwrite-this-file
|
||||
# IF YOU MODIFY THIS FILE, remove this comment.
|
||||
# otherwise, oTree will automatically overwrite it.
|
||||
otree>=5.0.0a21
|
||||
psycopg2>=2.8.4
|
||||
numpy>= 2.1.3
|
||||
1
runtime.txt
Normal file
1
runtime.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
python-3.11.5
|
||||
82
settings.py
Normal file
82
settings.py
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
from os import environ
|
||||
|
||||
SESSION_CONFIGS = [
|
||||
dict(
|
||||
name='test',
|
||||
app_sequence=['Task1'],
|
||||
completionlink='',
|
||||
use_captchas=0,
|
||||
num_demo_participants=5,
|
||||
context="test",
|
||||
),
|
||||
dict(
|
||||
name='prolific',
|
||||
app_sequence=['Start', 'Task1', 'Finish'],
|
||||
completionlink='https://app.prolific.com/submissions/complete?cc=C15TDZJ3',
|
||||
use_captchas = 1,
|
||||
num_demo_participants=6,
|
||||
estimated_completion_time=15,
|
||||
context="prolific",
|
||||
),
|
||||
dict(
|
||||
name='elfeonline',
|
||||
app_sequence=['Start', 'Task1', 'Finish'],
|
||||
elfecompletionlink = "https://qualtrics.ucl.ac.uk/jfe/form/SV_bKGyy84JJN8c7n8?",
|
||||
use_captchas = 1,
|
||||
num_demo_participants=6,
|
||||
estimated_completion_time=15,
|
||||
context="lab",
|
||||
),
|
||||
|
||||
]
|
||||
|
||||
# if you set a property in SESSION_CONFIG_DEFAULTS, it will be inherited by all configs
|
||||
# in SESSION_CONFIGS, except those that explicitly override it.
|
||||
# the session config can be accessed from methods in your apps as self.session.config,
|
||||
# e.g. self.session.config['participation_fee']
|
||||
|
||||
SESSION_CONFIG_DEFAULTS = dict(
|
||||
real_world_currency_per_point=1.00,
|
||||
participation_fee=2.50,
|
||||
participation_payment=2.50,
|
||||
bonus=3,
|
||||
min_bonus_payment=0,
|
||||
max_bonus_payment=20.00,
|
||||
min_payment=2.50,
|
||||
max_payment=2.50+20.00,
|
||||
currency_symbol='£',
|
||||
)
|
||||
|
||||
ROOMS = [
|
||||
dict(
|
||||
name='Test',
|
||||
display_name='Test',
|
||||
),
|
||||
dict(
|
||||
name='Prolific',
|
||||
display_name='Prolific',
|
||||
),
|
||||
dict(
|
||||
name='elfeonline',
|
||||
display_name='elfeonline',
|
||||
),
|
||||
]
|
||||
|
||||
PARTICIPANT_FIELDS = []
|
||||
SESSION_FIELDS = []
|
||||
|
||||
# ISO-639 code
|
||||
# for example: de, fr, ja, ko, zh-hans
|
||||
LANGUAGE_CODE = 'en'
|
||||
|
||||
# e.g. EUR, GBP, CNY, JPY
|
||||
REAL_WORLD_CURRENCY_CODE = 'GBP'
|
||||
USE_POINTS = True
|
||||
|
||||
ADMIN_USERNAME = 'admin'
|
||||
# for security, best to set admin password in an environment variable
|
||||
ADMIN_PASSWORD = 'templateadminpass'
|
||||
|
||||
DEMO_PAGE_INTRO_HTML = """ """
|
||||
|
||||
SECRET_KEY = '0112357121931'
|
||||
Loading…
Add table
Add a link
Reference in a new issue