<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Martijn Stegeman &#183; Archive</title>
    <link>https://www.stgm.nl/archive/</link>
    <atom:link href="https://www.stgm.nl/archive/feed.xml" rel="self" type="application/rss+xml" />
    <description>Notes and write-ups by Martijn Stegeman.</description>
    <language>en</language>
    <item>
      <title>Running check50</title>
      <link>https://www.stgm.nl/archive/2021/01/26/running-check50/</link>
      <guid isPermaLink="true">https://www.stgm.nl/archive/2021/01/26/running-check50/</guid>
      <pubDate>Tue, 26 Jan 2021 00:00:00 +0000</pubDate>
      <content:encoded>
&lt;p&gt;&lt;strong&gt;Martijn Stegeman, University of Amsterdam&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;step-1-getting-started&quot;&gt;Step 1. Getting Started&lt;/h2&gt;

&lt;p&gt;If you have a working Python installation, please run &lt;code&gt;pip3&lt;/code&gt; to install &lt;code&gt;check50&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;pip3 install check50
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should now be able to run the tool:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ check50
usage: check50 [-h] [-d] [--offline] [-l] [-o {ansi,json,html} [{ansi,json,html} ...]]
               [--target TARGET [TARGET ...]] [--output-file FILE]
               [--log-level {debug,info,warning,error}] [--ansi-log] [--no-download-checks]
               [--no-install-dependencies] [-V] [--logout]
               slug
check50: error: the following arguments are required: slug
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The reason that check50’s complaining is that it needs a &lt;strong&gt;slug&lt;/strong&gt;, a path to the checks that have to be run. These checks are usually hosted in a GitHub repository, which makes them easy to find. Let us now choose an assignment for which we have an existing check.&lt;/p&gt;

&lt;h2 id=&quot;step-2-the-assignment&quot;&gt;Step 2. The Assignment&lt;/h2&gt;

&lt;p&gt;The assignment we’re going to be working on is called “Hello”. It’s supposed to be a Python program that asks for a name, and then outputs “Hello, name!”. Looks like this when run at a command prompt:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ python3 hello.py
Name: Martijn
Hello, Martijn!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;For now, we’ll try to run the check without creating that program. As it happens, the slug for this program is &lt;code&gt;cs50/problems/2020/fall/sentimental/hello&lt;/code&gt;. From that slug, you can infer that it  lives in this location:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On github.com&lt;/li&gt;
  &lt;li&gt;In the organization &lt;code&gt;cs50&lt;/code&gt; (you can use your personal organization!)&lt;/li&gt;
  &lt;li&gt;In the repository &lt;code&gt;problems&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;In the branch &lt;code&gt;2020&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;In the folder &lt;code&gt;fall/sentimental/hello&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s run it by typing the slug and adding the flag &lt;code&gt;-l&lt;/code&gt; (lowercase letter). This ensures that the check is run on your own computer instead of Harvard’s cloud infrastructure.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This also means that check50 is only critically dependent on two things: the &lt;code&gt;pip&lt;/code&gt; infrastructure and the availability of a GitHub repository with checks. So anyone can use it at any time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code&gt;$ check50 cs50/problems/2020/fall/sentimental/hello -l
Connecting......
You seem to be missing these required files:
hello.py
You are currently in: ~/dev, did you perhaps intend another directory?
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Again, check50 is complaining, this time because a file called &lt;code&gt;hello.py&lt;/code&gt; is expected to be present. Check50 always runs checks on the files that are in the &lt;em&gt;current directory&lt;/em&gt;! So if you, or your students, want to check a program, they have to &lt;code&gt;cd&lt;/code&gt; into that directory.&lt;/p&gt;

&lt;p&gt;But that’s OK! Lets’ create an empty file called &lt;code&gt;hello.py&lt;/code&gt;. Let’s see what &lt;code&gt;check50&lt;/code&gt; says now:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ touch hello.py
$ check50 cs50/problems/2020/fall/sentimental/hello -l
Checking........
Results for cs50/problems/2020/fall/sentimental/hello generated by check50 v3.2.0
:) hello.py exists.
:( responds to name Emma.
    expected prompt for input, found none
:( responds to name Rodrigo.
    expected prompt for input, found none
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally it works! Of course, your empty solution in &lt;code&gt;hello.py&lt;/code&gt; shouldn’t pass all checks. And indeed, your empty program correctly fails two of those. Only the “hello.py exists” check passes now.&lt;/p&gt;

&lt;p&gt;Here are the three potential results that you may encounter for each check:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;:)&lt;/code&gt; is reported for any successful check&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;:(&lt;/code&gt; is reported when a check is run but fails&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;:|&lt;/code&gt; is reported when a check is not run, always because an earlier check failed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-3-what-checks-look-like&quot;&gt;Step 3. What checks look like&lt;/h2&gt;

&lt;p&gt;Have a look at this &lt;a href=&quot;https://github.com/cs50/problems/blob/2020/fall/sentimental/hello/__init__.py&quot;&gt;example check&lt;/a&gt; for &lt;code&gt;hello.py&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import check50

@check50.check()
def exists():
    &quot;&quot;&quot;hello.py exists.&quot;&quot;&quot;
    check50.exists(&quot;hello.py&quot;)

@check50.check(exists)
def veronica():
    &quot;&quot;&quot;responds to name Emma.&quot;&quot;&quot;
    check50.run(&quot;python3 hello.py&quot;).stdin(&quot;Emma&quot;).stdout(&quot;Emma&quot;).exit()

@check50.check(exists)
def brian():
    &quot;&quot;&quot;responds to name Rodrigo.&quot;&quot;&quot;
    check50.run(&quot;python3 hello.py&quot;).stdin(&quot;Rodrigo&quot;).stdout(&quot;Rodrigo&quot;).exit()
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As you can see, there are three checks:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;exists()&lt;/code&gt;, which does nothing more than verify the presence of the correct source files used in the remainder of the checks&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;veronica()&lt;/code&gt;, which checks if the program works correctly when fed the name “Emma”&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;brian()&lt;/code&gt;, which checks if the program works correctly when fed the name “Rodrigo”&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never mind those function names!&lt;/p&gt;

&lt;p&gt;From the example you may notice a few things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;There are dependencies between checks. The second and third check specify &lt;code&gt;exists&lt;/code&gt; as a precondition.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code&gt;&quot;&quot;&quot;docstrings&quot;&quot;&quot;&lt;/code&gt; atop each function are used as check descriptions when running &lt;code&gt;check50&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The check specifies a kind of “chain of events”, where expected input and output are specified, as well as the expectation of a clean exit.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Incidentally, the third check is fundamentally the same as the second one. It is a simple measure to ensure that the program isn’t hardcoded towards the name “Emma”. Of course, student code could be hardcoded in the following way and still pass the check:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;name = input(&quot;Name: &quot;)
if name == &quot;Emma&quot;:
    print(&quot;Hello, Emma!&quot;)
else:
    print(&quot;Hello, Rodrigo!&quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So you may want to write better checks to encourage students to write better code :-) But that’s something that can develop over the years!&lt;/p&gt;

&lt;h2 id=&quot;step-4-creating-your-own-checks-repo&quot;&gt;Step 4. Creating your own checks repo&lt;/h2&gt;

&lt;p&gt;To get started, create a GitHub repository and add a subfolder for the check that you would like to write. Then you need two files at a minimum:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A file called &lt;code&gt;__init__.py&lt;/code&gt; that contains the actual check code, like you’ve seen in step 3.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;And a file called &lt;code&gt;.cs50.yml&lt;/code&gt; that contains some of the basic configuration for your check. Most importantly, it specifies which files (from the current user directory) to include in the check and which to ignore. You can also use it to include distribution modules or other features specific to your course.&lt;/p&gt;

    &lt;p&gt;Here is an &lt;a href=&quot;https://github.com/cs50/problems/blob/2020/fall/sentimental/hello/.cs50.yml&quot;&gt;example&lt;/a&gt; that shows the basics:&lt;/p&gt;

    &lt;pre&gt;&lt;code&gt;  submit50:
    files: &amp;amp;submit50_files
      - !exclude &quot;*&quot;
      - !include &quot;*.py&quot;
      - !require hello.py

  check50:
    files: *submit50_files
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;Note that only Python &lt;code&gt;.py&lt;/code&gt; files are taken into account for the check, and besides, the file &lt;code&gt;hello.py&lt;/code&gt; is required. You might imagine a very eager student who has completely modularized their code into multiple Python files. Using &lt;code&gt;!include&lt;/code&gt; to allow &lt;code&gt;*.py&lt;/code&gt; ensures that these external modules are available when checking.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-5-creating-checks-for-jupyter-notebooks&quot;&gt;Step 5. Creating checks for Jupyter Notebooks&lt;/h2&gt;

</content:encoded>
    </item>
    <item>
      <title>Setting up Slack for your students</title>
      <link>https://www.stgm.nl/archive/2020/03/12/setting-up-slack-for-your-students/</link>
      <guid isPermaLink="true">https://www.stgm.nl/archive/2020/03/12/setting-up-slack-for-your-students/</guid>
      <pubDate>Thu, 12 Mar 2020 00:00:00 +0000</pubDate>
      <content:encoded>
&lt;p&gt;&lt;strong&gt;Martijn Stegeman, University of Amsterdam&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our goal is to provide students an environment where they can help each other. This is why traditionally, in our &lt;a href=&quot;https://www.mprog.nl/&quot;&gt;Minor Programmeren&lt;/a&gt; programming courses, we require attendance for substantial hours, up until 40 hours a week.&lt;/p&gt;

&lt;p&gt;Because we currently don’t want students to be &lt;a href=&quot;https://www.uva.nl/&quot;&gt;on campus&lt;/a&gt;, we need other solutions. To allow students to help each other out in times of frustration, or simply to resolve a bug, we provide Slack. Here is the why and how.&lt;/p&gt;

&lt;h2 id=&quot;why-slack&quot;&gt;Why Slack?&lt;/h2&gt;

&lt;p&gt;We want to provide an easy entry for students who haven’t used online communications much. In Slack, which is mostly text-based, it’s easy to join and lurk around a little. You don’t have to participate right away.&lt;/p&gt;

&lt;p&gt;However, Slack also allows person-to-person chats and even audio calls with screen sharing. Simply click another user’s name and press “Call”. Person-to-person chat can’t be disabled, which is why we have most staff &lt;strong&gt;not&lt;/strong&gt; join the Slack account. We want to avoid situations where staff is seen as “permanently available”. (However, we will be using an online planning tool via which students can book a 1-on-1 video chat with a teaching assistant.)&lt;/p&gt;

&lt;h2 id=&quot;one-slack-for-our-programming-courses&quot;&gt;One Slack for our programming courses&lt;/h2&gt;

&lt;p&gt;We decided to put all students of our programming-related courses together. These are often students that are currently in a fulltime programming course, or they come from different parts of the university. &lt;strong&gt;In general&lt;/strong&gt;, we would recommend creating a Slack account for each study programme, or for each cohort of students.&lt;/p&gt;

&lt;h2 id=&quot;one-big-channel-per-course&quot;&gt;One big channel per course&lt;/h2&gt;

&lt;p&gt;To facilitate quick and low-bar discussions about our courses, we created channels for each course.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Web programming (multiple groups of students doing roughly the same course)&lt;/li&gt;
  &lt;li&gt;Parttime programming (introductory courses in parttime)&lt;/li&gt;
  &lt;li&gt;Fulltime programming (introductory courses in fulltime)&lt;/li&gt;
  &lt;li&gt;Scientific programming (an introductory course with a different approach)&lt;/li&gt;
  &lt;li&gt;Collective intelligence (an advanced course for a different audience)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;https://www.stgm.nl/archive/2020/03/12/setting-up-slack-for-your-students/channels.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;optionally-channels-for-groups-of-students&quot;&gt;Optionally, channels for groups of students&lt;/h2&gt;

&lt;p&gt;In Collective Intelligence, students will be teaming up in groups of three. These students need a way to convey their progress on their projects to course leaders. Creating a channel for each group also gives them a natural place to discuss between them.&lt;/p&gt;

&lt;h2 id=&quot;settings&quot;&gt;Settings&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;We keep the &lt;code&gt;general&lt;/code&gt; channel for very general announcements; for example about the technical infrastructure that’s shared by all courses. We disable posting to &lt;code&gt;general&lt;/code&gt; by anyone other than admins. (See “Manage posting permissions” in the channel options.)&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://www.stgm.nl/archive/2020/03/12/setting-up-slack-for-your-students/general.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;We restrict all channel management options to admins only., including the creation of new channels. If students want, they can still create multi-person chats. However, we ask them to talk about the course in the public channels as much as possible.&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;https://www.stgm.nl/archive/2020/03/12/setting-up-slack-for-your-students/permissions.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;feedback&quot;&gt;Feedback&lt;/h2&gt;

&lt;p&gt;Have anything to share about your use cases for Slack? Send me an e-mail and I’ll post a link for others!&lt;/p&gt;
</content:encoded>
    </item>
  </channel>
</rss>
