oTree Studio: display form fields differently for different participants in the experiment - application-design

I am new to oTree and oTree Studio, so I apologise in advance if my question doesn't make much sense. I am also new to Stack Overflow, so I apologise if I am duplicate a question.
I am writing an application for a lab experiment using oTree Studio. During that experiment, participants are given a series of “opportunities” to exchange resources in the form of “points” having monetary value. The opportunities are organised into rounds and, in a given round, each participant can share her resources with up to 2 other participants. Importantly, a participant cannot transfer her resources to herself; the resources can only be transferred to another participant.
Now, in each round, all the participants in the experiment, except for the given one, are listed on the screen. The participant is then asked, for each of the other subjects, if she wants to transfer her resources to that participant. To that end, I have created an integer field form for each participant which takes value of 1 if the participant transfers her resources to the particular recipient and 0 (the default value) otherwise. The point is that the form field corresponding to the given actor is hidden to keep the participant from transferring the resources to herself. I did it as follows:
{% if player.id_in_group != 1 %} {% formfield player.ile1 %} {% else %} {% endif %}
The problem, however, is that once the participants completes the screen and clicks on “Next”, an error message is displayed saying
Please fix the errors in the form.
One can try to avoid the problem by allowing “empty” forms, so that the hidden form field corresponding to the given participant can be left unfilled. But then I cannot impose additional restrictions, such as limiting the number of potential recipients to 2. I mean I have defined the following error message for participants:
if values['ile1'] + values['ile2'] + ... > 2: return 'The maximum number of recipients exceeded.'
But then the application fails and displays an error message saying
unsupported operand type(s) for +: 'NoneType' and 'int'
So, I guess, what I am looking for is a way to combine these two things: (a) allowing for the form fields to be left unfilled and, at the same time, (b) applying a restriction on the maximum number of recipients. Does anybody know how to do this?

Use get_form_fields to show different fields depending on self.player.id_in_group: https://otree.readthedocs.io/en/latest/forms.html#determining-form-fields-dynamically

Related

Webi: On opening, filter data by current user name which can be in or not in a given list (no prompt)

(SAP BusinessObjects BI Platform 4.3 Support Pack 1 Patch 11 Version : 14.3.1.4142.11)
Disclosure: I'm not born english speaking, but if I have understood correctly, we should now use "they", instead of he/she, etc. That is what I did here. Just to be sure no one is confused while reading.
Hi everyone, it's me again for a webi question.
I have this report in which I have data for a group of workers. These data are: their name, when they work, where, which activity they do, etc.
Worker name
Other information
Worker A
...
Worker B
...
...
...
Worker M
...
Worker Z for example is not in the list.
I currently have a filter "name" (multi-list), which allows us to select one or more workers (Worker A, Worker B,...). By default, it shows all data.
There is an auto-refresh on opening.
The function CurrentUser() returns the worker ID, not the name.
Worker name
Worker ID
Worker A
238x01f93
Worker B
4j192h60a
...
...
Worker Z
09ad812jn
I have two kind of user, that can see this report:
A user whose name is present in the list of workers (e.g. Worker A).
A user whose name is not present in the list of workers (e.g. Worker Z).
My goal:
When the user opens the report, the filter "name" is set by default with their name (e.g. Worker A). This way, they see only their data. If they want to see the data of other workers, they can easily change the filter to select other workers (e.g. Worker B and C). It should not be limited.
When the user (Worker Z) opens the report, they see all data. They can naturally use the filter to select only one or a few workers if they want to.
What I did/tried:
I can change things in the view (database), in the universe or/and in the report. I only tried things on the report level, because I could not see any ways to help me solve this on universe or view level. (But I am open to suggestions! :-) )
Create a variable to:
Filter for only current user ID. It worked, but only if the user name was in the list. Another problem is that the workers don't know this user ID and can't work with it.
=CurrentUser()
Search in the list, if the current user ID exists. Does not work. It shows always all data.
If (Pos([Personalnumber];CurrentUser()) > 0) Then CurrentUser() Else [Personalnumber]
Link the current worker ID with their name if they are in the list. It worked well for them, but I could not find a way to have all workers, if the current user name is not in the list.
If (CurrentUser() = [Personalnumber]) Then [Name] Else "All"
I read so many posts, but none for my case. It is often to prevent user to see all the data, which is not what I want. They should be able to see everything, if they want to.
We only want to filter for the current user for performance means and also efficiency. The user does not have to select themselves the right filter and loose time. Most of the time, they only wants to see their data.
Can anyone help me?
Don't hesitate to tell me if something is unclear or missing. :-)
Thanks for your time!

How in REDCap do you create a [survey-url] to a new instance of a Repeating Instrument?

How do you send a [survey-link] that creates/links to a new instance of a repeating-instrument survey in REDCap?
ie imaging you have customers who should visit you on a regular basis. You have two instruments:
customer
visit [set as a Repeating Instrument + enabled as a Survey]
And you have an alert that regularly sends them a "Time for your next visit" email.
When I send an alert to a customer with [survey-link:visit] it will work the first time. The email will contain a unique URL for that customer's visit. But when the alert is sent a second time, person will open the URL and get a "Thank you for your interest, but you have already completed this survey."
I can manually (via the web admin) create a new instance of their Visit. But how should I do this automatically?
Thank you.
As of version 12.5 this is now supported using a smart variable [new-instance] which, when appended to a [survey-url] or [survey-link] smart variable, will target a new instance of the instrument if it is repeating. In the same release came ASI options around repeating instruments, which allow you to repeat an ASI every X minutes, hours or days, and each successive ASI instance points to the specific instance of the survey instrument. This is useful for daily surveys.
For your use case, [survey-link:visit][new-instance] will do what you want. Send it to them once and instruct them to fill it out as many times as needed, or send it however many times you need to.
====
Yes, this is a current limitation. It has been requested of the REDCap developers to add a smart variable [new-instance] that can be appended to a [survey-link] or other smart variable to instantiate a new instance of a repeating instrument, and they have responded positively.
Maybe the most appropriate workflow here would be for you or the project staff to manually create the visit instance, save it with a date, and have an alert that sends them an invitation to complete the visit details, or whatever you need them to do.
If you want the respondents to instantiate the visit themselves (i.e., make a booking rather than respond to a booking made on their behalf), the only workaround I have personally managed is to enable the survey queue and activate the repeating instrument on the basis of some logic (say, [consent] = 1), and in the survey settings of the repeating instrument, enable the option to Allow respondents to repeat the survey.
With these settings, the survey queue will allow the survey respondent to create a new instance of the instrument themselves by clicking the 'Take this survey again' button (button text configurable in survey settings). They can be emailed their link to the survey queue via an alert using the smart variable [survey-queue-link] or [survey-queue-url].
For extra credit, you could get fancy with the survey queue logic so that the instrument is disabled if, say, the last instance of the survey has today's date, using something like [consent] = 1 and datediff([visit_date][last-instance],"today","d",true) > 0. With this you could prevent them smashing it and adding multiple new visits at once.

Return back to the same place in the dialog tree after switching between intents in Amazon LEX

Giving I have a dialog tree for booking a rental car.
The bot have a main Intent called "orderIntent" and a second intent called "colorIntent".
In the "orderIntent" dialog the user will be asked to chose for a car category, date, and price (all of those have a separate slot in this intent).
I want that the at any given moment in the dialog the user will be able to call the "colorIntent" intent and set up a color as he desires and when this is finish, to return back to the same place in the tree dialog that he previously left.
For example, when the user will be asked to pick a date for the booking, and will reply with "I want to chose a green color for the car" this will invoke the "colorIntent" intent and the user will be able to chose a color.
Afterwards the user should return to the same part of the dialog that he partially fulfilled and will be asked again to pick the date of the booking. I want to achieve that while maintaining the information he already partially fulfilled in the main dialog about the car catagory and price he already picked and the new information about the color he picked from the "colorIntent" intent.
How can I configure such logic in the AWS Lambda of the bot ?
https://github.com/awslabs/serverless-application-model/blob/master/examples/apps/lex-book-trip-python/lambda_function.py
Try seeing book_car function this will solve your problem. Because here they are taking some slot values of book_hotel and setting up in book_car.
Make use of sessionAttributes to achieve this because sessionAttributes remain across intents, while slots are only held within each intent.
Intent_A logic can run, filling slots as it goes, and the slot values should also be saved in sessionAttributes. Then at any point of IntentA, a user could trigger Intent_B.
Now Intent_A's slots are overwritten by Intent_B's slots but Intent_A's slot values are still saved in sessionAttributes.
Extra Information on how to change between intents:
You then have 2 choices:
(1) force the user to trigger IntentA again
with a prompt like, "To continue booking the car, please say, book a
car".
(2) use confirmIntent back to IntentA, but it will need to
ask a confirmation question like, "Would you like to continue booking
a car?" The response to that will go to Intent_A regardless, so
inside of Intent_A you need to just check the confirmationStatus
which will be either "Confirmed" or "Denied", based on how the
user responded to that question. If confirmed, then you can continue
Intent_A, and if denied, then you should close Intent_A.
(look into confirmIntent here under types of dialogAction)
After getting back into Intent_A, you should then check if any slot data is inside of sessionAttributes, and force this data back into the appropriate slots. Then your original logic can detect which slots are already filled, and continue where it left off.

how to approach a reward system [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have a website where I've done a "mission generator" to encourage engagement. I've hard coded 3 sets of missions (Easy, Med, Hard).
Easy missions have 6-8 cases that could randomly happen
Update N times your hero (N is random number)
Update specific skill
Rest your hero for a day
etc..
Med and Hard require 1 task which is harder to achieve and adds two from the Easy tasks.
My generator works great but I would like to know how to design the reward system so that it is hard to game by the users.
The problems that I have are sort of:
The user might decide to quickly achieve the tasks and then delete them as soon as they get the "achieved badge"
For example
Update 3 times your hero
Add a new skill
Send a message to another hero
What I see as a problem is that the person might decide to update 3 times, choose a new skill and send a message, then erase the 3 updates (there is such a feature) remove the skill and delete the message that he has send.
So far I've come up with the following ideas but I'm looking for an opinion from someone who has done something like that.
- First approach:
Hard-code a table in the database with columns for each possible combination say
row1 - Updates | row2 - New skills etc...
Downside: I'm afraid that the row could end up very long and it would be hard to manage and add new types of challenges. The whole concept become very rigid.
- Second Approach:
For every task assign a unique id and once a skill or update or whatever is added append that to the task number.
Downside: every member gets 3 daily missions (which could be extended in time) if the generator requires on average 3 updates per mission that makes it to roughly 10 updates per user per day, adding to that the actual records for the updates with the data it adds up pretty quickly for a couple of thousand users. I would say 90% of this data will be useless and will just generate bills.
- Third approach:
Add a column to the table with the updates, skills (and all the other tables which are used in the missions). Then, when the user adds a new skill (for instance) the challenge ID will be added to the column in the skills table, then if the skill is removed the mission will fall back to "unachieved" (same goes for the updates and the other skills)
Downside: This might turn out very messy when the challenge is "put hero to rest for 1 day" because if the generator asks that twice between two days, the user will lose the first achievement of that sort because the challenge ID will be overwritten.
A big question is - what happens when the user decides to cut corners and delete some of their skills. I presume their missions will start piling up? (kind of like a punishment)
Try making some things more dynamic.
For example: You could put the skills in a static checkbox list on the side, and select or deselect them. Then add a button to delete the selected skill, and skills are added to the static checkbox list by selecting a skill on the page itself, outside of the checkbox list.
The skill is then added to the checkbox list as an element.
When you need to rest your character for a day, it's pretty much impossible to do that twice in one day. Make it so that the rest for a day event can only happen once in a day.
This way there is no need to worry about overwriting, and the player doesn't get confused as to why his hero needs to rest twice. Perhaps make the resting bound to a stamina bar that decreases with certain events. When you add a skill perhaps the training can cost stamina. When the stamina runs out his hero needs to rest.
About removing updates and skills:
It is not a very good idea to make things removable right after being added.
Make it so that the skills and updates can only be removed after a certain time.
Long enough to confirm the achievement and store the achievement.
Then they are able to remove their skill and updates and the achievement which was already saved won't disappear.
Sending a message to the other hero:
I have a question about that.
Why would you be able to remove the message.
Is the message sent to another player?
If so, it would make no sense to be able to remove it.
Also, sending a message obviously happens server side since it goes to another player so you can set it to done server side.

Efficiently check unread count on entire account

To my understanding, there is no way to query an entire IMAP account for a total unread count, or the UIDs of all recent messages, regardless of mailbox. That to get a total unread count for the account, you need to iterate over all mboxes and check their status. I've done that, but it's very slow (45 seconds on one of my accounts with many mailboxes).
Mail.app can find new messages, even in deeply nested mailboxes, in just a couple seconds.
Is the speed here just a limitation of using Net::IMAP? Or am I missing some functionality that will return a more limited set of mailboxes, like only ones that have RECENT messages?
The only other option I can think of to use response handlers, and also keep a cache of which mboxes have a counter > 1, and then only check the combination of the two each cycle. But since I'm looking to do this in a script, eliminating the need to carry over a cache would be ideal, if not required.
The canonical way to detect new messages in IMAP is via UIDNEXT. Issuing
A001 STATUS "foldername" (UIDVALIDITY UIDNEXT)
on each folder that you care about will give you the expected next UID for that folder. Here's what the RFC has to say:
Unique identifiers
are assigned in a strictly ascending fashion in the mailbox; as each
message is added to the mailbox it is assigned a higher UID than the
message(s) which were added previously. Unlike message sequence
numbers, unique identifiers are not necessarily contiguous.
The next unique identifier value is the predicted value that will be
assigned to a new message in the mailbox. Unless the unique
identifier validity also changes (see below), the next unique
identifier value MUST have the following two characteristics. First,
the next unique identifier value MUST NOT change unless new messages
are added to the mailbox; and second, the next unique identifier
value MUST change whenever new messages are added to the mailbox,
even if those new messages are subsequently expunged.
So just keep track of the each folder's expected next UID and UID validity value. If a STATUS command results in either UIDNEXT or UIDVALIDITY changing from your cached value, you know you need to check for new mail (if the former) or resync (if the latter).
Something like this:
imap.status("foldername", ["UIDNEXT", "UIDVALIDITY"])

Resources