On this page:
6.1 Studies
study?
make-study
run-study
6.2 Steps
step?
make-step
make-step/  study
step-page?
page
next
done
6.2.1 Step Widgets
button
form
skip
6.3 Data Storage & Retrieval
get
get/  instance
put
put/  instance
get-current-round-name
put-current-round-name
get-current-group-name
put-current-group-name
transition-graph
8.12

6 Reference🔗

 (require congame/components/study) package: congame-core

6.1 Studies🔗

A study is a series of steps and a transition graph that controls which steps transition to which steps.

procedure

(study? v)  boolean?

  v : any/c
Returns #t when v is a study.

procedure

(make-study name    
  steps    
  [#:requires requires    
  #:provides provides    
  #:transitions transitions    
  #:view-handler view-handler    
  #:failure-handler failure-handler])  study?
  name : string?
  steps : (listof step?)
  requires : (listof symbol?) = null
  provides : (listof symbol?) = null
  transitions : (or/c #f (hash/c symbol? any/c)) = #f
  view-handler : (or/c #f (-> request? response?)) = #f
  failure-handler : (or/c #f (-> step? any/c step-id/c)) = #f
Creates a study that can be run by run-study. The name argument is used in debugging and in the admin interface. Any step that is part of the study has to be listed in steps.

The #:transitions argument has to be a transition-graph that provides all the transitions between the steps. See transition-graph for details.

procedure

(run-study s [req #:bindings bindings])  any/c

  s : study?
  req : request? = (current-request)
  bindings : (hash/c symbol? any/c) = (hasheq)
Runs the study s under req with bindings.

6.2 Steps🔗

A step is any page that can be used to relay information to a participant or collect information from them (or both).

procedure

(step? v)  boolean?

  v : any/c
Returns #t when v is a step.

procedure

(make-step id    
  handler    
  [transition    
  #:view-handler view-handler    
  #:for-bot bot-handler])  step?
  id : symbol?
  handler : (-> step-page?)
  transition : transition/c = (lambda () next)
  view-handler : (or/c #f (-> request? response?)) = #f
  bot-handler : (or/c #f procedure?) = #f

procedure

(make-step/study id    
  s    
  [transition    
  #:require-bindings require-bindings    
  #:provide-bindings provide-bindings])  step?
  id : symbol?
  s : study?
  transition : transition/c = (lambda () next)
  require-bindings : (listof binding/c) = null
  provide-bindings : (listof binding/c) = null
Creates a step that executes s when reached.

The #:require-bindings argument maps identifiers required by s to identifiers available in the current study context if the name is different – otherwise it assumes that required identifers share names and attempts to set them accordingly.

The #:provide-bindings argument maps identifiers in the current study that should be mapped to some subset of the identifiers provided by s upon completion. When #:provide-bindings is null?, no values are assigned.

For example:

(make-step/study
  'required-tasks
  task-study
  #:require-bindings '([n task-treatment])
  #:provide-bindings '([root-success? success?]))

Here, n in task-study will take on the value of task-treatment, and after running, root-success? will be assigned the value of success? in the parent.

procedure

(step-page? v)  boolean?

  v : any/c
Returns #t when v is a step page.

syntax

(page maybe-validator expr ...+)

 
maybe-validator = 
  | #:validator validator-expr
 
  validator-expr : (-> any/c xexpr?)
Within a step, page ensures that the setup actions are not run again in case the page contains a form that is submitted and fails validation. Specifically, consider a page containing a form:

For example:

(define (step-with-setup-and-form)
  (perform-a-once)
  (perform-b-once)
  (page
   (begin
     (perform-c-again)
     (haml
       (:h1 "The Form")
       ;; some form
       ;; ...
       ))))

When the user lands on step-with-setup-and-form the first time, resumes there, or refreshes the page, perform-a-once and perform-b-once will be called. If the user submits the form and it fails validation, the page will be reloaded showing the error messages and the fields filled with the inputs that were valid. However, neither perform-a-once nor perform-b-once will be run again, while perform-c-again will be run again.

It is possible to pass a custom validator for xexprs to page to provide better error messages.

canary

next : any/c

canary

done : any/c

Special values that can be used as transition results to cause a study to transition to the next step or to the end of the study, respectively.

6.2.1 Step Widgets🔗

procedure

(button action    
  label    
  [#:id id    
  #:to-step-id to-step-id])  xexpr?
  action : (-> void?)
  label : xexpr?
  id : string? = ""
  to-step-id : (or/c #f symbol?) = #f
Renders a button with the given label that executes action when pressed. After the action is executed, moves the participant to the step named by to-step-id or the next step if to-step-id is #f.

The #:id argument is useful for identifying the button within bot handlers.

procedure

(form f    
  action    
  render    
  [#:id id    
  #:enctype enctype])  xexpr?
  f : form?
  action : (-> void?)
  render : (-> (widget-renderer/c) xexpr?)
  id : string? = ""
  enctype : string? = "multipart/form-data"
Renders the form represented by f using render and executes action on successful submission, then continues to the next step in the study.

The #:id argument is the same as for button.

procedure

(skip [to-step-id])  void?

  to-step-id : symbol? = #f
Skips to the step named by to-step-id or the next step in the study if to-step-id is #f.

6.3 Data Storage & Retrieval🔗

A step scope represents the region of the database where data for a study is stored and retrieved from. Step scope is determined by the combination of the current participant, the study stack and optional round and group information. Instance scope is shared between participants to a study instance.

procedure

(get k    
  [default    
  #:round round-name    
  #:group group-name])  any/c
  k : symbol?
  default : (or/c any/c (-> any/c))
   = (λ () (error 'get "value not found for key ~.s" k))
  round-name : string? = ""
  group-name : string? = ""
Retrieves the value stored under the symbol k for the current step scope. If no such value exists, default is called if it is a procedure, or returned if it is a value.

procedure

(get/instance k default)  any/c

  k : symbol?
  default : (or/c any/c procedure?)
Like get, but retrieves data from instance scope.

procedure

(put k    
  v    
  [#:round round-name    
  #:group group-name])  void?
  k : symbol?
  v : any/c
  round-name : string? = ""
  group-name : string? = ""
Stores v under the symbol k for the current step scope.

procedure

(put/instance k v)  void?

  k : symbol?
  v : any/c
Like put, but stores data in instance scope.

procedure

(get-current-round-name)  string?

procedure

(put-current-round-name round-name)  void?

  round-name : string?
Controls the current round for participants in a study.

procedure

(get-current-group-name)  string?

procedure

(put-current-group-name group-name)  void?

  group-name : string?
Controls the current group for participants in a study.

 (require congame/components/transition-graph)
  package: congame-core

syntax

(transition-graph transition-clause ...+)

 
transition-clause = [id transition-entry ...+]
     
transition-entry = --> transition-target
     
transition-target = id
  | (unquote transition-lambda)
     
transition-lambda = (lambda () transition-expr ...+)
  | (lambda name:id () transition-expr ...+)
     
transition-expr = (done)
  | (fail expr)
  | (goto id:id)
  | expr
A transition-graph consists of one or more transition-entries. For example:

(make-study
  "some study"
  #:transitions
  (transition-graph
    [a --> b --> (unquote(lambda ()
                    (if succes-step-b?
                      (goto bad-ending)
                      (goto good-ending))))]
    [fail-ending --> fail-ending]
    [good-ending --> good-ending])
  (list
    (make-step 'a a)
    (make-step 'b b)
    (make-step 'c c)))