Jeremy

Forum Replies Created

Viewing 15 posts - 781 through 795 (of 1,522 total)
  • Author
    Posts
  • in reply to: DragDrop features #7143
    Jeremy
    Keymaster

    Hi Alex,

    Here is a template/demo project featuring the DragDrop element that you might be interested in taking a look at: https://farm.pcibex.net/r/MOytaR/

    2. the main purpose of Canvas elements is precisely to control visual layout, in particular when you need to print two elements side by side. Here’s an example, printing two Canvas elements side by side:

    
    newCanvas("container", 400, 200)
      .add( 0,0, newCanvas("pink patch", 200,200).color("pink")) 
      .add( 0,0, newCanvas("blue patch", 200,200).color("blue"))
      .print()
    

    3. look at the code of the first trial in the demo project I shared above to see an example

    Jeremy

    in reply to: Customize slider #7137
    Jeremy
    Keymaster

    Hi,

    If you haven’t read it yet, I recommend you take look at this guide: Adding custom CSS

    However the code I use to parse CSS at the PCIbex Farm has some bugs, so it’s often a better idea to edit global_main.css directly rather than relying on PennController.css automatically prefixing class names with PennController-. Another tricky thing is that when generating class names from element names, PennController will drop all underscores (_) so your Scale element’s CSS class name will be MainSlider, not Main_Slider

    Here is what I added to global_main.css to get the desired rendering:

    .PennController-MainSlider {
      width: 100%; /* Width of the outside container */
    }
    
    /* The slider itself */
    .PennController-MainSlider input {
      -webkit-appearance: none;  /* Override default CSS styles */
      appearance: none;
      width: 100%; /* Full-width */
      height: 25px; /* Specified height */
      background: #d3d3d3; /* Grey background */
      outline: none; /* Remove outline */
      opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
      -webkit-transition: .2s; /* 0.2 seconds transition on hover */
      transition: opacity .2s;
    }
    
    /* Mouse-over effects */
    .PennController-MainSlider input:hover {
      opacity: 1; /* Fully shown on mouse-over */
    }
    
    /* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
    .PennController-MainSlider input::-webkit-slider-thumb {
      -webkit-appearance: none; /* Override default look */
      appearance: none;
      width: 25px; /* Set a specific slider handle width */
      height: 25px; /* Slider handle height */
      background: #04AA6D; /* Green background */
      cursor: pointer; /* Cursor on hover */
    }
    
    .PennController-MainSlider input::-moz-range-thumb {
      width: 25px; /* Set a specific slider handle width */
      height: 25px; /* Slider handle height */
      background: #04AA6D; /* Green background */
      cursor: pointer; /* Cursor on hover */
    }
    

    Let me know if you have questions

    Jeremy

    in reply to: Conditional training phase #7136
    Jeremy
    Keymaster

    Hi Giorgio,

    If you have many blocks, I recommend the following approach:

    var blocks = ["block1","block2","block3","block4"];
    fisherYates(blocks);
    
    Sequence("intro",...blocks,"results")
    

    Jeremy

    in reply to: DragDrop features #7135
    Jeremy
    Keymaster

    Hi Alex,

    It is wiser to keep the debugger on until you’ve shared the data-collection link with your participants. For example, after I copied your project, I re-activated the debugger and noticed your project uses PennController 1.9, when the DragDrop element was introduced in 2.0.

    After I uploaded the most recent version of PennController.js to the Modules folder, the experiment started to run but stayed on the preloading page with the debugger complaining:

    Found an existing Image element named “fish-plural”--using name “fish-plural2” instead for new element

    Indeed, at line 43 you have newImage("fish-plural") when it should be getImage("fish-plural")—the experiment would try (and fail) to preload an inexistent image with the filename fish-plural2

    After I fixed that, the debugger no longer threw error messages, but I was still unable to drag the image: I looked up the Log tab of the debugger and noticed that the last command was add on the “drag” Canvas element, when it should have been wait on the DragDrop element if everything had run smoothly. And indeed, at line 36 you have .add(getImage("fish-plural")): coordinates are missing here, so PennController is trying to interpret the reference to the image as an X coordinate, and crashes (I should make the debugger throw an error message in such cases)

    After I provide coordinates to that add command, things work… -ish. Because the Canvas elements are created with no dimensions (e.g. newCanvas("gap-0")) they technically occupy no space on the page, and end up overlapping one another( (although uou can still see “gap-1” because it is printed 250px to the right of the left edge of the Canvas element). Giving them a size, for example 200×200 (newCanvas("gap-0", 200,200)) improves things: I can now drag and drop the image onto gap-0 or gap-1, and the trial will complete as expected (however it’s not easy to see with gap-1, because the text is printed 250px to the right, out of bounds of a 200×200 canvas)

    Note that because you print your Text elements onto Canvas elements, you don’t need any of the center, unfold or print commands you call on them: the add command will print them at the provided coordinates at once when executed. So here’s an optimized code (I added background colors to the canvases to delineate them visually):

    newCanvas("gap-0", 200,200)
            .add( "center at 50%", "middle at 50%", newText("gap0"))
            .color("lightblue")
            .center()
            .print()
            .log() //remember this
        ,
        newCanvas("gap-1", 200,200)
            .add( "center at 50%", "middle at 50%", newText("gap1"))
            .color("pink")
            .center()
            .print()
            .log() //remember this
        ,
        newCanvas("drag", 200,200)
            .add(0,0,newImage("fish-plural", "2fishRoundTank.png").size(200, 200) )
            .center()
            .print()
            .log()
        ,
        newDragDrop("dd")
            .addDrop(getCanvas("gap-0"),getCanvas("gap-1"))
            .addDrag(getImage("fish-plural"))
            .offset(25) // will pin the elements to (25,25) from the top-left edge of the dropzone
            .single()
            .log()
            .wait()
    

    Thank you for the suggestion about including a demonstration feature for code blocks on the documentation, it’s something I would like to implement one day, but unfortunately I cannot dedicate time to it at the moment

    Jeremy

    in reply to: Conditional training phase #7130
    Jeremy
    Keymaster

    Hi,

    The code you posted has several syntax errors that make it crash. If it comes from an existing project, please consider sharing the demonstration link. Or, if you directly report some code here, try to copy-paste it from the existing project so no new errors are introduced in the process

    This is the code I tested myself, after fixing the syntax errors:

    AddTable("LEX",`WORDS,RES
    PLATERY,F
    DENIAL,J
    GENERIC,J
    MENSIBLE,F
    SCORNFUL,J
    STOUTLY,J
    ABLAZE,J
    JERMSHAW,F`)
    
    Template("LEX", row=> 
        newTrial("Engl_prof",
            newVar("score", 0).global()
            ,
            newText(row.WORDS).print("center at 50vw","middle at 50vh")
            ,
            newText("<span style='color:red'><b>F = it doesn't exist</span>>/b>, <span style='color:green'><b>J = it exists</span></b>")
                .print("center at 50vw","middle at 75vh")
            ,
            newKey("lext","FJ")
                .wait()
                .log()
                .callback(
                    getKey("lext")
                        .test.pressed(row.RES)
                        .success(getVar("score").set(v=>v+1))
                )
        )
    )
    
    newTrial("result",
        newVar("score").global(),
        newText("yscore")
            .before(newText("Your score is: "))
            .text(getVar("score"))
            .after(newText("/60"))
            .print()
        ,
        newButton("Ok").print().wait(),
        newVar("score").global(),
        getVar("score").test.is( v => v > 41 )
            .success(end)
            .failure( newText("I'm sorry but your score is too low. You cannot continue the experiment.").print().wait() )
            
    )

    When I ran the experiment, the debugger immediately reported an error:

    Ambiguous use of getVar(“score”): more than one elements were created with that name-- getVar(“score”) will refer to the first one
    

    Indeed, in the second newTrial you create the “score” Var element twice, so I took the second one out, and then I was able to run the experiment with no warnings or errors

    Your main problem here is that you associate a callback to the Key element after a keypress happened. In fact you don’t need to use callback at all: all you want to do is wait for a keypress, and do something after that (namely, a test) and wait already gives you that:

    newKey("lext","FJ")
        .wait()
        .log()
        .test.pressed(row.RES)
        .success(getVar("score").set(v=>v+1))
    

    Now, your “result” (“resul” in your original code) trial checks whether the value of the “score” Var element is greater than 41, but since your table only defines 8 trials, of course you’ll never pass that threshold, even with a perfect score. 70% of 8 is 5.6, so you could replace 41 with 5. You could also print the “OK” button only if the test is a success, thus only letting the accurate participants continue:

    newTrial("result",
        newVar("score").global(),
        newText("yscore")
            .before(newText("Your score is: "))
            .text(getVar("score"))
            .after(newText("/8"))
            .print()
        ,
        newButton("Ok"),
        getVar("score").test.is( v => v > 5 )
            .success(getButton("OK").print())
            .failure( newText("I'm sorry but your score is too low. You cannot continue the experiment.").print() )
        ,
        getButton("OK").wait()
    )
    

    One caveat: it is against some recruitment platforms’ policies (and maybe some IRB policies?) to prevent a participant who started your experiment from completing it, so this is something you might want to double-check

    Jeremy

    in reply to: consentLink in IinitiateRecorder is not blue? #7126
    Jeremy
    Keymaster

    Hi Shereen,

    I am not sure why this happens, since the Message-continue-link class should apply the desired aesthetics. Try replacing consentLink.html with consentLink.text, in case some related HTML tags gets lost in the process

    Jeremy

    in reply to: Saving Recordings with Appropriate Filename #7124
    Jeremy
    Keymaster

    Hello,

    You are using row as your pointer (Template("REAL_NDS", row => newTrial("ndsr",) not variable: replace variable with row and it should work

    Jeremy

    in reply to: syntax acceptability judgment – pictures and template #7122
    Jeremy
    Keymaster

    You could use .button() on your Scale element and add this to Aesthetics/PennController.css:

    .Scale label {
        padding: 1em;
        color: blue;
        margin: 1em;
        border: solid 1px gray;
    }

    Jeremy

    in reply to: syntax acceptability judgment – pictures and template #7120
    Jeremy
    Keymaster

    Hello,

    You can use the Scale element:

    Template("design.csv", variable =>
        newTrial("experimental-trial",
            newImage("target", variable.foto)
              .size("25vw","auto")
              .print()
            ,
            newText("sentence", variable.sentence)
              .center()
              .print()
            ,
            newScale("acceptability", 7)
              .before( newText("(very bad)") )
              .after( newText("(very good)") )
              .callback( getText("warning").hidden() )
              .center()
              .log()
              .print()
            ,
            newText("warning", "Please provide a judgment before you can continue").center().color("red").hidden().print()
            ,
            newButton("continue", "Proceed")
              .print()
              .center()
              .wait( getScale("acceptability").test.selected().failure(getText("warning").visible()) )
              .log()
        )
    )

    You should not turn the debugger off until you start collecting data from your first participant

    Jeremy

    in reply to: Https / SSL on ibex webserver #7116
    Jeremy
    Keymaster

    Hello,

    I moved this topic to the support section, seeing you’re not requesting new features on PennController or the farm

    If you follow the step-by-step CGI instructions from the documentation the experiment won’t be served on port 3000. Then you should move any multimedia file from chunk_includes to the www directory, so they can be found at the same path as experiment.html

    I haven’t had troubles relating to SSL following these steps before

    Jeremy

    in reply to: MediaRecorder #7113
    Jeremy
    Keymaster

    Hello Jana,

    The documentation has a guide on how to set up multimedia recording. You need to save a .php file with the content from the code block under “Server setup” and upload it to your webserver. There exist commercial services to obtain webserver space (eg. DreamHost) and some institutions (eg. universities) also provide some webserver space to their members. Google Drive cannot be used to run PHP scripts (it’s a cloud service, not a webserver)

    Alternatively, you can send the recordings to an S3 bucket, but the setup is somewhat more complicated in this case

    Let me know if you have questions,
    Jeremy

    in reply to: unable to download 'results' #7110
    Jeremy
    Keymaster

    Hi Umesh,

    Thank you for your message, I found out that one service has been down for ~3h. I restarted it, and as far as I can tell, it has now caught up with queued operations, and I am able to generate results files again. Let me know if you still cannot access your students’ results files

    Jeremy

    in reply to: High number for results #7108
    Jeremy
    Keymaster

    Hello,

    As you found out, attempting to generate large results files results in timeouts, which means you need to download them in chunks (and ideally delete them once you’ve made sure you fetched everything)

    Besides start and end of trials, which are automatically logged by default, anything PennController reports in the results file comes from a log command. If your instructions were committed to the output, chances are that you used .log on the element (eg. a Text element) which prints the instructions

    You are free to use the standard Ibex Farm to develop, host and run your PennController experiments, all you need to do is upload PennController.js to the js_includes folder. Note that that farm does not provide hosting of multimedia resources

    Jeremy

    in reply to: MTurk completion code #7104
    Jeremy
    Keymaster

    Hello,

    You can use .log("code", code) on the closing parenthesis of newTrial()

    Jeremy

    in reply to: code doesn't get updated despite the 'saved' message #7101
    Jeremy
    Keymaster

    Hi Umesh,

    Thank you for reporting this bug. I am familiar with it, but have not yet been able to identify what causes it to happen. However, I found that it seems to be tied to the project itself, so it will probably keep happening with that specific project (and any other affected project) but you might still have projects for which it doesn’t happen. What you can try to do is duplicate your project and see if the problem persists with the copy. If not, I’d say keep working on the copy

    Jeremy

Viewing 15 posts - 781 through 795 (of 1,522 total)