finger voting – teamwork and voting

In the past month, I’ve used “finger voting” in three contexts.

What is finger voting?

Voting with your fingers of course. Seriously thought, finger voting is a bit like rock, paper scissors. First the choices are presented. Then everyone sticks out their fist when ready to vote. The person who called the finger vote says 1, 2, 3, reveal and everyone votes at the same time. This could be thumbs up/thumbs down/thumbs side to indicate agreement/disagreement/neutrality. Or it can be a series of options. One finger means we should have pizza, two fingers means we should have sandwiches. Finger voting can be used for binding votes or polls.

Why is finger voting beneficial?

Decisions by consensus often take a long time. Sometimes the decision is such that any of the outcomes are acceptable. Sometimes at topic has been discussed at length and more discussion isn’t going to change anything. Sometimes you just want to take the pulse of the room to see if there is a consensus before spending a long time discussing. Finger voting lets you see where everyone stand.

Another benefit of finger voting is that the quieter people in the group get an equal say. It avoids the scenario where you have one vocal person in favor, one vocal person opposed and it appears the room is split down the middle. A finger vote/poll lets you see if it is split down the middle or just that one vocal person.

Context 1 – Work

We use finger voting for a variety of things. Some examples:

  • Process changes at the retrospective
  • Design decisions after discussing the options
  • To see how people feel about the sprint at the end of sprint planning

Context 2 – FRC (FIRST Robotics Challenge) Brainstorming

This year there were a number of strategies you could use for the robot. This decision is important because you get locked into it pretty quickly. There were a few conversations we got mired in. I suggested a finger vote to see what the majority of the room was thinking. While this worked, I learned that not being able to “demand” a finger vote makes it take much longer. At work, when anyone on the team suggests a finger vote, we have one. It may be a finger vote poll or a “binding” decision (well until the next retrospective). But a call for a finger vote at work isn’t distanced from said vote by a period of half an hour.

Context 3 – FLL (FIRST Lego League) judging

Today, I judged technical/robot design. The way judging works, there are four pairs (or triples) of judges who all see different teams and created an ordered list. Then the four groups get together to form a combined ordered list of X teams. To do this each group talks about their strongest team and all four groups concur on who was strongest overall. Then the next highest from that group replaces it and all four groups concur and…  Historically, the step of figuring out which of four teams should be ranked highest is a difficult step because you need at least eight people to agree. And typically that means the vocal people have a disproportionate impact on the decision.

Today, there 9 judges (three pairs and one triple) for technical/robot design. Two of us have been doing it for many years. I asked Dave (the other veteran judge) if I could moderate. He graciously agreed and I gave finger voting a shot.

Each group presented their strongest team and why. Then we used our fingers to show which of the four teams was strongest. Majority rules. And we proceeded. There were two votes that were really close and we discussed more there. There was even one where we had a three way tie. We discussed and revoted and there was no tie. (If there was another tie, I was going to propose we vote for which of the three was the weakest and see if we could get it down to two.)

Anyway, finger voting rocks. Consider it on your teams!

FIRST – FLL vs FTC judges training

I’ve been volunteering as a judge at FLL (FIRST Lego League) and FTC (FIRST Tech Challenge) for many years. This year the difference in certification was interesting. After all, why would you use the same system for the same organization?

FLL FTC
Video/educational materials Required* Optional
Quiz/cert test Required Required
Area to discuss quiz/other topics No Yes
Calls ? Optional
In person training ? Optional

The FLL training videos were horrible. There’s no option to speed up play. Many online videos let you play it at 2X the initial speed. Most of the material is the basics if you’ve been doing it for years. (Apparently I’ve never been certified as a judge for FLL). And you can’t skip even a small section of it to “fast forward”. The system actually records how many minutes the video is open. Well, you get what you measure.

What makes it worse is that the cert is completely optional as judges can be walk ons or corporate volunteers who show up the day of and have barely heard of FIRST.

I passed both certs on the first shot. I didn’t need the training. I did enjoy the survey at the end.

building smart dashboard with gradle

FRC (FIRST Robotics Challenge) uses Ant to build the robot code. I think this is a wise choice since some teams are “internet challenged.” This hasn’t changed. What has changed since last year is that SmartDashboard uses Gradle to build. Our team is thinking about customizing Smart Dashboard this year which means we need to be able to build it.

Yesterday in the FRC lab, one of the StuyPulse team members asked me about Gradle. (I gave a really good overview of Ant last year so they remembered I knew build tools.) I explained the concepts of Maven/Gradle especially the local repository and dependencies. And I verbally explained how to run it. We didn’t get to do so together as there were other priorities for the day. And a lot of people weren’t at the meeting due to a competing school event. So I’m writing everything down in this post.

Building Smart Dashboard

The discussion was centered around building SmartDashboard. If you aren’t involved with a FIRST Robotics Competition team, this is a Java based UI used when running the robot. Conveniently that project comes with Gradle right in the project. So all you have to is:

  1. cd to directory you cloned SmartDashboard in
  2. chmod 700 gradlew
  3. ./gradlew build

Make sure you have internet before running this the first time. If you want to build directly from Eclipse, see my Eclipse Gradle post

Where is the output when building SmartDashboard

Running gradle creates a build directory. If you are using Eclipse, remember to hit refresh before looking for it. This build directory  contains a number of things:

  • distributions – a zipped up and tarred up version of SmartDashboard which includes the jar file, all need dependencies and the script to kick it off. This is what you need
  • classes – the compiled .class files
  • libs – a jar file with the compiled code in this project
  • reports – how well did you follow the coding standards established for this project
  • scripts – to launch SmartDashboard
  • temp – would you really expect to find something important in a directory named temp?

What does the Gradle build file do?
Gradle is a build tool. The build.gradle file in SmartDashboard contains Groovy code that declares what the build should do. Both Gradle and Maven follow “convention over configuration” which means that a lot is implied! I went over most (but not all) of this out loud in the classroom.

A plugin is like a helper tool that Gradle is going to use in order to build. For example, ‘java’ is going to compile among other things.  Most of these plugins are in common use. I hadn’t heard of the shadow before. A quick look tells me that it builds an uber jar (which is a distribution file that contains all the dependencies). That’s really useful. In fact, I have used the shade plugin which does the same thing in Maven. The WPILibVersioningPlugin is obviously specialized code for FIRST.

plugins {
    id 'java'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '1.2.4'
    id 'maven-publish'
    id 'idea'
    id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '1.6'
    id 'checkstyle'
}

Gradle needs to download files in order to run. This includes the plugins that we just saw along with dependencies – jars that the program needs. These files are hosted in a repository for binary files. A really common one is Maven Central. This is used by both Maven and Gradle builds to obtain binaries.

repositories {
    mavenCentral()
}

Those dependencies I just mentioned? Here they are. In this case, the dependencies are WPI code and common open source tools like JUnit (a testing library). Notice how all of these except the WPI one use the same format – three strings separated by colons? There’s a reason for this. When accessing Maven Central, you specify a GAV. This stands for group id/artifact id/version. The colons separate them. For example, jfree is a group id, jfreechart is an artifact id and 1.0.13 is a version.

Note that none of these four exhibits a “normal” GAV. You are supposed to use a fully qualified name for the group id. Just like we do for Java package names. An artifact id is lower case “words” separated by dashes if there is more than one word. Finally, you have an optional version number.  There can also be some optional information like a classifier that tells you what file extension you need. The WPI example does have a good group id. And the others have good artifact ids and versions. For more on the WPILib group id see this post.

dependencies {
    compile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop'
    compile 'junit:junit:4.12'
    compile 'jfree:jcommon:1.0.16'
    compile 'jfree:jfreechart:1.0.13'
}

Next the script specifies that we should create a jar file and an uber jar file named SmartDashboard.

jar {
    baseName = 'SmartDashboard'
}
shadowJar {
    baseName = 'SmartDashboard'
}

Now you see that this really is a Groovy script; it even has an if statement.

// Ensure that the WPILibVersioningPlugin is setup by setting the release type, if releaseType wasn't
// already specified on the command line
if (!hasProperty('releaseType')) {
    WPILibVersion {
        releaseType = 'dev'
    }
}

If the artifact is being published, details are here. WPI is publishing to this FIRST WPI Maven repo. They use the WPI Version Plugin and publish to the local Maven repo – which is the FIRST WPI Maven repo on their build server. (clarified in comment 65)

publishing {
    publications {
        maven(MavenPublication) {
            artifact(shadowJar) {
                classifier null
            }
            groupId 'edu.wpi.first.wpilib'
            artifactId 'SmartDashboard'
            version WPILibVersion.version
        }
    }
}

Getting close to the end. Now the build configuration says to use the coding conventions in the checkstyle.xml file. This is good. It means that people will have to follow coding conventions if they contribute back to SmartDashboard.

checkstyle {
    configFile = new File(rootDir, "checkstyle.xml")
    toolVersion = '6.19'
    if (project.hasProperty("ignoreCheckstyle")) {
        ignoreFailures = true
    }
}

In Java, you can automatically configure a Jar to run a certain class’ main method when you run the jar. This is specified in the manifest. Gradle can generate this manifest for you.

mainClassName = "edu.wpi.first.smartdashboard.SmartDashboard"

SmartDashboard comes with a fakeRobot test project. This is a submodule from Gradle’s point of view so it needs a build config too. Luckily you already know what plugins, dependencies and a main class are so this should be clear.

project(':fakeRobot') {
  apply plugin: 'java'
  apply plugin: 'application'

  dependencies {
      compile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop'
  }

  mainClassName = "edu.wpi.livewindowfakerobot.LiveWindowFakeRobot"
}

The end! The very last thing is to declare which version of Gradle this entire script should be run with.

task wrapper(type: Wrapper) {
    gradleVersion = '3.3'
}
  1.  

Output from building in gradle

I’m including the output from a “good” run in case you have problems and want to compare. This is for the first time you run it. After that the download steps won’t be in the output and it will run much faster.

$ ./gradlew build
Downloading https://services.gradle.org/distributions/gradle-3.3-bin.zip
..................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Unzipping /Users/jeanne/.gradle/wrapper/dists/gradle-3.3-bin/64bhckfm0iuu9gap9hg3r7ev2/gradle-3.3-bin.zip to /Users/jeanne/.gradle/wrapper/dists/gradle-3.3-bin/64bhckfm0iuu9gap9hg3r7ev2
Set executable permissions for: /Users/jeanne/.gradle/wrapper/dists/gradle-3.3-bin/64bhckfm0iuu9gap9hg3r7ev2/gradle-3.3/bin/gradle
Starting a Gradle Daemon (subsequent builds will be faster)
Download https://plugins.gradle.org/m2/com/github/jengelman/gradle/plugins/shadow/1.2.4/shadow-1.2.4.pom
Download https://plugins.gradle.org/m2/gradle/plugin/edu/wpi/first/wpilib/versioning/wpilib-version-plugin/1.6/wpilib-version-plugin-1.6.pom
Download https://plugins.gradle.org/m2/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.pom
Download https://plugins.gradle.org/m2/org/apache/ant/ant/1.9.4/ant-1.9.4.pom
Download https://plugins.gradle.org/m2/org/apache/ant/ant-parent/1.9.4/ant-parent-1.9.4.pom
Download https://plugins.gradle.org/m2/org/codehaus/groovy/groovy-backports-compat23/2.4.4/groovy-backports-compat23-2.4.4.pom
Download https://plugins.gradle.org/m2/org/ajoberstar/grgit/1.7.0/grgit-1.7.0.pom
Download https://plugins.gradle.org/m2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.pom
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit/4.3.1.201605051710-r/org.eclipse.jgit-4.3.1.201605051710-r.pom
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit-parent/4.3.1.201605051710-r/org.eclipse.jgit-parent-4.3.1.201605051710-r.pom
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit.ui/4.3.1.201605051710-r/org.eclipse.jgit.ui-4.3.1.201605051710-r.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.jsch/0.0.9/jsch.agentproxy.jsch-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy/0.0.9/jsch.agentproxy-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.pageant/0.0.9/jsch.agentproxy.pageant-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.sshagent/0.0.9/jsch.agentproxy.sshagent-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-jna/0.0.9/jsch.agentproxy.usocket-jna-0.0.9.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-nc/0.0.9/jsch.agentproxy.usocket-nc-0.0.9.pom
Download https://plugins.gradle.org/m2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.pom
Download https://plugins.gradle.org/m2/org/slf4j/slf4j-parent/1.7.21/slf4j-parent-1.7.21.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch/0.1.53/jsch-0.1.53.pom
Download https://plugins.gradle.org/m2/com/googlecode/javaewah/JavaEWAH/0.7.9/JavaEWAH-0.7.9.pom
Download https://plugins.gradle.org/m2/org/sonatype/oss/oss-parent/5/oss-parent-5.pom
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.core/0.0.9/jsch.agentproxy.core-0.0.9.pom
Download https://plugins.gradle.org/m2/com/github/jengelman/gradle/plugins/shadow/1.2.4/shadow-1.2.4.jar
Download https://plugins.gradle.org/m2/gradle/plugin/edu/wpi/first/wpilib/versioning/wpilib-version-plugin/1.6/wpilib-version-plugin-1.6.jar
Download https://plugins.gradle.org/m2/org/ow2/asm/asm-commons/5.0.3/asm-commons-5.0.3.jar
Download https://plugins.gradle.org/m2/org/apache/ant/ant/1.9.4/ant-1.9.4.jar
Download https://plugins.gradle.org/m2/org/codehaus/groovy/groovy-backports-compat23/2.4.4/groovy-backports-compat23-2.4.4.jar
Download https://plugins.gradle.org/m2/org/ajoberstar/grgit/1.7.0/grgit-1.7.0.jar
Download https://plugins.gradle.org/m2/org/apache/ant/ant-launcher/1.9.4/ant-launcher-1.9.4.jar
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit/4.3.1.201605051710-r/org.eclipse.jgit-4.3.1.201605051710-r.jar
Download https://plugins.gradle.org/m2/org/eclipse/jgit/org.eclipse.jgit.ui/4.3.1.201605051710-r/org.eclipse.jgit.ui-4.3.1.201605051710-r.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.jsch/0.0.9/jsch.agentproxy.jsch-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.pageant/0.0.9/jsch.agentproxy.pageant-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.sshagent/0.0.9/jsch.agentproxy.sshagent-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-jna/0.0.9/jsch.agentproxy.usocket-jna-0.0.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.usocket-nc/0.0.9/jsch.agentproxy.usocket-nc-0.0.9.jar
Download https://plugins.gradle.org/m2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch/0.1.53/jsch-0.1.53.jar
Download https://plugins.gradle.org/m2/com/googlecode/javaewah/JavaEWAH/0.7.9/JavaEWAH-0.7.9.jar
Download https://plugins.gradle.org/m2/com/jcraft/jsch.agentproxy.core/0.0.9/jsch.agentproxy.core-0.0.9.jar
No .git was found in /Users/jeanne/Documents/workspace/SmartDashboard, or any parent directories of that directory.
No version number generated.
:compileJava
Download http://first.wpi.edu/FRC/roborio/maven/development/edu/wpi/first/wpilib/networktables/java/NetworkTables/3.1.5-20170105171843-1-g3e2631f/NetworkTables-3.1.5-20170105171843-1-g3e2631f.pom
Download https://repo1.maven.org/maven2/jfree/jcommon/1.0.16/jcommon-1.0.16.pom
Download https://repo1.maven.org/maven2/jfree/jfreechart/1.0.13/jfreechart-1.0.13.pom
Download http://first.wpi.edu/FRC/roborio/maven/development/edu/wpi/first/wpilib/networktables/java/NetworkTables/3.1.5-20170105171843-1-g3e2631f/NetworkTables-3.1.5-20170105171843-1-g3e2631f-desktop.jar
Download https://repo1.maven.org/maven2/jfree/jcommon/1.0.16/jcommon-1.0.16.jar
Download https://repo1.maven.org/maven2/jfree/jfreechart/1.0.13/jfreechart-1.0.13.jar
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:assemble
:checkstyleMain
Download https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/6.19/checkstyle-6.19.pom
Download https://repo1.maven.org/maven2/org/antlr/antlr4-runtime/4.5.3/antlr4-runtime-4.5.3.pom
Download https://repo1.maven.org/maven2/org/antlr/antlr4-master/4.5.3/antlr4-master-4.5.3.pom
Download https://repo1.maven.org/maven2/commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
Download https://repo1.maven.org/maven2/com/puppycrawl/tools/checkstyle/6.19/checkstyle-6.19.jar
Download https://repo1.maven.org/maven2/org/antlr/antlr4-runtime/4.5.3/antlr4-runtime-4.5.3.jar
Download https://repo1.maven.org/maven2/commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.jar
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:checkstyleTest UP-TO-DATE
:test UP-TO-DATE
:check
:build
:fakeRobot:compileJava
:fakeRobot:processResources UP-TO-DATE
:fakeRobot:classes
:fakeRobot:jar
:fakeRobot:startScripts
:fakeRobot:distTar
:fakeRobot:distZip
:fakeRobot:assemble
:fakeRobot:compileTestJava UP-TO-DATE
:fakeRobot:processTestResources UP-TO-DATE
:fakeRobot:testClasses UP-TO-DATE
:fakeRobot:test UP-TO-DATE
:fakeRobot:check UP-TO-DATE
:fakeRobot:build

BUILD SUCCESSFUL

Total time: 1 mins 9.099 secs