Tetsu=TaLowの雑記(はてブロ版)

しがない大学教員が琵琶湖のほとりから呟きます

Googleフォームを使った簡易電子投票システム

この記事はKMC Advent Calendar 2018の9日目の記事になる予定でした。でも大幅遅刻…。8日目は現在KMC最年少部員のkanaさんによる16年間を振り返って整理する - kana_kmcのブログでした。16!私の1/3以下ですねぇ。趣味色々楽しい時期ですねぇ。でも、まずは受験頑張って下さいね!と思ってしまうのは大学教員の性でしょうか。

adventar.org

ごあいさつ

こんにちは、Tetsu=TaLowです(kmc-idはtetsu)。京大マイコンクラブ(KMC) 32回生です。現役最年長部員(51歳)です。KMCは誰でも部費さえ払えば会員になれるので、私のようにはるか昔に学生だった者でも会員で居続けられるのです。今年も年甲斐もなくAdventarに登録してみたのは、今年はついに忙しくて秋のKMC OB会もでられなかったので、これくらいしないとKMC的活動が全然できなくないなと思ってのことでした。一昨年は毒にも薬にもならない話を、昨年はちょっとは役に立つかもしれない話を書きましたが、今年は「もしかしたら、人によっては、役に立つ、かもしれない、くらいの話」を書いてみたいと思います。あ、その前に12月9日は素数日ですよね。今年はあと2回、12月23日と29日に素数日があるのですが、来年最初の素数日は2月21日までないのですよね。その代わり1月以外には全て素数日があります。総数は19日と今年より1日多いのですが、連続素数日双子素数日もなく、いとこ素数日(差が4日)が1組、セクシー素数日(差が6日)が2組ありますね。

20190221
20190227
20190301
20190319
20190323
20190421
20190523
20190529
20190601
20190613
20190719
20190811
20190823
20190913
20191009
20191027
20191109
20191117
20191231

最近素数日botと化している私のTwitterアカウントですが、来年も呟いていこう*1と思いますのでよろしくお願いします。

きっかけはCSSx2.0での投票

ところで皆さん、投票ってやりますよね。選挙権は18歳以上なら普通持っているはずなので議員や首長を選ぶ選挙は機会があるはずですし、仕事なんかでもたまに投票の機会があるかもしれません。私は大学教員という仕事をしている関係からか、教授会や学位審議委員会での各種議決投票、学会の役員選挙など日常的に投票してますので、割と投票の機会が多い人間だと思います。ですが、これらは、いまだに紙の投票が多いのですよね。集計大変なのに…でも色々考えると、匿名性と二重投票防止を確保しつつ電子投票にするってそれなりのインフラが必要でなかなか難しい。しかし、こうすれば簡単に実現できるんじゃないのかな、というアイデアはいくつか温めてました。でもそれを実装しようにも、そもそも私って投票する側に回ることはあっても、投票を取りまとめる側になることってあまりなかったんですよね。

それが、今年割と大きな投票を取りまとめる羽目に陥ったのです。

日本のセキュリティ研究者の大きな集まりの一つに情報処理学会コンピュータセキュリティ研究会(CSEC)が主催する「コンピュータセキュリティシンポジウム(通称CSS)」があります。このCSSではキャンドルスターセッション(CSSx2.0)と呼ばれる、いわゆるランプセッション*2があり、ここで各発表について投票が行われるのですが昨年のCSS2017のCSSx2.0で私うっかり優勝してしまいまして*3(キャンドルスター1等星という称号が与えられる)、今年の実行委員長を拝命してしまったのです。ということは投票を管理しないといけないわけですが、これまではこの投票が原始的でして…発表会場で投票用紙が配られ、これに良かったと思われる発表の番号を書いて退場時に投票箱に放り込むだけなんですよね。しかも、この投票がキャンドルスター賞を選ぶためと、別の特別賞(CSS2017の場合にはアルタイル賞)を選ぶための2つ投票が行われるわけですが、この投票用紙がセットになっちゃってます。こんな感じ。

f:id:tetsutalow:20181209021405p:plain

委員長引継ぎで受け取った投票用紙

はい見事なネ申Excelですね!これを印刷して、4つに切って配って、投票してもらったらそれを集計するわけです。しかも集計はキャンドルスター賞と特別賞で2回やらなきゃいけない。それを500人分やるとかちょっとやりたくないよなぁと。そこで強く決意したわけですよ。今年のキャンドルスターセッションでは電子投票に置き換えてやると!というわけで、前からちょっと温めてたアイデアをこの際、実装してみることにしました。それも、最小の手間で(これ重要)。

電子投票システムの設計

実際に投票システムを考えるにあたっては以下のことに注意しました。

  1. 新規のシステムを作るのは面倒なので、ありあわせのものだけで構築すること。
  2. 2重投票が防止できること。
  3. 投票の匿名性は保たれること。
  4. 投票はスマホやパソコンからできるだけ平易に行えること。
  5. 会場にスマホもパソコンも持ちこまない人がいるかもしれないので、紙でも投票可能なこと。
  6. 集計が楽になること。

まず1.ですが、そのため道具立ては以下のもので十分なようにしました。

2.と5.を実現するために、投票用紙を配ることにしました。その投票用紙に投票用コードを書いておき、ネット経由での投票時にそれを入力してもらうことにしました。投票者は会場に来ることが前提になっているので、全投票用紙に個別の投票用コードを印刷しておいて、一人1枚配ることにすれば2重投票は防止できますし、コードを十分予測困難にすればイタズラ投票も防止できるでしょう。投票用紙をランダムに配れば匿名性も保たれ、3.も実現できます。スマホやパソコンを持たない人には投票用紙を会場の投票箱に投入してもらいますが、それを回収した後に事務局側でそれを改めてネット投票してしまえば、集計はネット上でできるので6.も実現できるはずです。

ということで、こんなシステムにしました。

f:id:tetsutalow:20181209051755p:plain

投票の流れ

これなら、スマホとPCから入力されたものはGoogleフォームを通じてGoogleスプレッドシート上に集計できるようになるはずです。この際、Google Apps Scriptを使って2重投票のチェックもしてしまえば後が楽になります。できるだけ紙投票ではなくネット投票して下さいと呼びかけて成功すれば、集計の負荷も下がるでしょう。さて、これを出来るだけ少ない手間で実現しちゃいましょう。

投票システムの実装

投票用コードの生成

投票用コードは、少なくとも投票する人数分は用意する必要があります。今回は1000人分作ってみました。投票用コードはスマホ入力の際にはQRコードに埋め込んでしまうことにしますが、PCから投票する人には手入力してもらうことになるので、誤入力が少なくて済むように、読み間違えやすい0とO(ゼロとオー)、1とIやl(イチとアイやエル)が混在しないように考えます。投票の匿名性を確保し不正を防ぐという意味では、容易に覚えられない長さがあった方がいいはずです。数字だけで12桁とかでもいいかなと思ったのですが、Excelでの扱いやすさを優先して今回は大文字のアルファベットのみ10文字で生成してみました。プログラミング言語はPython3。このまま手元にコピペして実行していただいてもいいですが、Google Colaboratoryを使っているのでこのままWeb上でも実行可能です*4

generatecodes.ipynb

…まぁ実は1000個くらいならこんなコードを書くまでもなくて、こちらのExcelシート(Google Spreadsheetですが)を使ってもいいかと思います。とてもダサい方法ですが*510文字の投票用コードを1000個生成してくれます。厳密にはPython版と違って重複チェックしてないのですが、1000人なら重複しちゃう確率は十分低いでしょう*6
docs.google.com

これを使って必要な数の投票用コードが入ったCSVファイルをまず作ります。上記プログラムを使った人は出力をファイルに落として 投票用コード.csv とでもして保存したあと、それを開いて先頭行(1行目)に空行を挿入して見出し行にします。A列の見出し行は「投票用コード」とでもしましょう。上記ExcelシートをExcel形式(.xlsx)でダウンロードした人は*7、そのままだと投票用コードが再計算のたびに変わってしまうので、一度CSV形式で保存してから再度そのファイルを開いて関数を消します。いずれにせよ、出来上がりはこんな状態になっているはずです。

f:id:tetsutalow:20181209093346p:plain

投票用コードを用意したところ

とりあえずこれは置いておいて、次はGoogleフォームの準備です。

Googleフォームを使った投票フォームの作成

ここでは投票に使うGoogleフォームを投票フォームと呼びますが、これを作ります。Googleフォームの使い方については他にも多く記事があるのでお任せするとして、ポイントだけご紹介します。

  • 入力項目の先頭は投票用コードにします。入力項目としては必須にします。入力形式を記述式にします。回答の検証はオンにして、正規表現で入力内容をチェックした方がいいでしょう。

f:id:tetsutalow:20181211085421p:plain

投票用コードの入力欄
  • 投票する項目はラジオボタンにしておくのが楽です。入力必須項目にするかどうかは白票を許すかどうかに依存しますが、必須にしておいた方がトラブルが少ないと思います。どうしても白票を許したければ「白票」とか「棄権」という項目を作るといいでしょう。

f:id:tetsutalow:20181209121615p:plain

投票項目の設定
  • 回答はスプレッドシートに集約されるようにします。回答タブを押し、右側の縦に点が3つ並んだメニューアイコン*8をクリックして回答先を選択し、新しいスプレッドシートを作成するように選びます。

f:id:tetsutalow:20181209130424p:plain

回答をスプレッドシートに集計するようにする(1)

f:id:tetsutalow:20181209131304p:plain

回答をスプレッドシートに集計するようにする(2)
  • 設定ボタン(ブラウザ画面右上の、歯車みたいなアイコン)を押して、収集時の挙動を設定します。重要なのは「回答を1回に制限する」をチェックしないことです。チェックするとGoogleアカウントにログインして回答することを要求するので、投票の匿名性が失われてしまいます。同様にメールアドレスを収集するのも投票では意味ありませんよね。回答者が行える操作の2つについてはよく考えて使った方がいいでしょう。「送信後に編集」は状況によっては便利ですが、例えば投票者が端末を共用する可能性がある時には人の投票が見えてしまうのでやめた方がいいです。設定の「プレゼンテーション」のタブで投票後に出るメッセージが指定できますが、固定メッセージしか出せないのであまり気の利いたことはできません。

    f:id:tetsutalow:20181210090345p:plain

    投票フォームの挙動の設定

    f:id:tetsutalow:20181210091051p:plain

    投票受付時のメッセージを設定


入力用URLの取得

次に、作った投票フォームへ飛ぶためのURLを2種類取得します。

  1. 既定値が入ったURLの取得。このためにはまず、フォームの右上のメニューをクリックして「事前入力したURLを取得」を選びます。

    f:id:tetsutalow:20181209134443p:plain

    既定値が入ったURLの取得


    そうすると作成中の投票フォームが現れるので、既定値を入れるべき質問項目にデータを入力して「リンクを取得」を押します。ここでは投票用コードに仮の値を入力します。

    f:id:tetsutalow:20181209150950p:plain

    既定値を入力してURLを取得する

    すると

    https://docs.google.com/forms/d/e/1FAIpQLScEiLaxf9HM7ulrLQDx0dI-wyk3zUDZ8W8xY0U6615WA4CTvQ/viewform?usp=pp_url&entry.1077401194=ABCDEABCDE
    のようなURLが手に入ります(指示されたとおりに操作するとクリップボードにリンクがコピーされます)。この最後のentry.1077401194が投票用コードを既定値にするためのURLパラメータになります。各投票用紙には投票用コードを印刷するのですが、スマホ向けにはこれを既定値として組み込んだURLをQRコードとして印刷すれば、投票者は楽に投票できるはずです。

  2. 上記のURLのうち、先頭からviewfromまでを抜き出します。これが既定値のないURLになります。例えば今回の例だと
    https://docs.google.com/forms/d/e/1FAIpQLScEiLaxf9HM7ulrLQDx0dI-wyk3zUDZ8W8xY0U6615WA4CTvQ/viewform
    になります。このURLはパソコンで投票する人向けに投票用紙に書くのですが、さすがにこんな長いURLを手で入力させるのは困難なので、bit.lyを使って短縮します。単に縮めるだけでなく、わかりやすい名前を付けると入力が楽になります。今回はhttp://bit.ly/KinokoTakenokoとしてみました。

 これらのURL、一度確定するとフォームを編集しても変わりません。なので、例えば投票項目や内容がまだ固まっていない段階でURLだけ取得してしまい、先に投票用紙を作っておいて、あとで投票項目を調整してもいいでしょう。実際CSSx2.0では発表者は直前まで決まらないので、フォームを作って投票用紙を印刷するところまでは前もってやっておき、当日直前に投票項目を作りました。

 投票用紙を作る

次に投票用紙を作ります。投票用紙に必要なのは

  • 投票用コード
  • PC入力用のURL(投票フォーム)
  • スマホ入力用の、投票用コードが既定値としてセットされた投票フォームのURLをQRコードにしたもの
  • 手入力用の記入欄

です。このうち、特にスマホ入力用のQRコードを楽に作成したいので、まず投票用紙の数だけURLが入ったExcelシートを作ることにします。

先ほど作成した投票用コードが入ったCSVファイルを開いて、これのB列に「既定値として投票用コードが入ったURL」を作ります。例えばB2セルをこのようにします。

=CONCAT(”https://docs.google.com/forms/d/e/1FAIpQLScEiLaxf9HM7ulrLQDx0dI-wyk3zUDZ8W8xY0U6615WA4CTvQ/viewform?usp=pp_url&entry.1077401194=”,A2)

CONCATの第1引数はさきほど得たURLのうちABCDEABCDEを除いたものです。これをオートフィルで引き伸ばせばB列が「投票用コードが既定値としてセットされた URL」になります。こんな感じですね。

f:id:tetsutalow:20181210030547p:plain

URLに投票用コードを反映させる

B列の見出しは「投票用コード入りURL」としておきました。このファイルを「投票用コード.xlsx」として保存して、これを使って投票用紙の印刷に使います。

docs.google.com

投票用紙はWordの差し込み印刷で作りました。Wordの差し込み印刷はわかりにくい機能ですけど、使いこなせれば非常に強力です。特に私はバーコード印刷がお気に入りです。さくっと作ってしまいましょう。

f:id:tetsutalow:20181210044924p:plain

投票用紙作成の様子

紙記入の場合の記入欄は白紙でももちろんいいし、事前に投票項目が決まっていればこういう風に丸をつけるように作ってもいいでしょう。

余談ですが、世の中Wordの罫線が使いにくいという人が多いのですが私は全然気にならないのですよね…むしろExcelの罫線の方が使いにくいです。Wordの罫線は「表のプロパティ」などを駆使するときっちり高さや幅がmm単位指定すれば、思った通りの表が固定的に作れると思ってます*9。なので、今回もまず表だけ作りました。1つのA4の紙から投票用紙を8枚作るようにレイアウトを決めて、まず左上の1枚だけを作ります。なお、これに差し込み印刷しますので、「1ページ以内に収まるように作ること」「データによって1ページに収まらないことがあると困るので、ページの下方は少し余裕を残しておくこと」はちょっとしたコツです。

これに、「投票コード」の右に投票用コードを、右側の欄にQRコード差し込み印刷されるようにすれば投票用紙は完成です。そのためにまず差し込むデータを指定します。「差し込み文書」タブの「宛先の選択」*10「既存のリストを使用」を選び*11、先ほどの「投票用コード.xlsx」を指定します。

f:id:tetsutalow:20181210082419p:plain

差し込み印刷用のデータの指定

投票用コード.xlsxの場合Excelシートなので、複数のシートに分かれていることがあります。そのせいか、.xlsxファイルを差し込み印刷のデータに使おうとするとシートを指定させられます。たとえシートが1枚であっても。なお、今回の私のデータの場合はcodes.csvから作ったのでシート名がcodesになってますが、多くの人はSheet1かもしれません。ポイントは「先頭行をタイトル行として使用する」にチェックをいれておくことです。

f:id:tetsutalow:20181210082640p:plain

データが入ったシートの指定

次に差し込みフィールドを挿入していきます。元のシートだと、投票用コードが入ったA列の見出しが「投票用コード」、これがセットされたURLが入ったB列が「投票コード入りURL」となっていたので、リボンの「差し込みフィールドの挿入」をクリックするとこんな感じになります。

f:id:tetsutalow:20181210091840p:plain

差し込みフィールドの選択

これを使って、投票用紙の「投票コード」の後ろに「投票用コード」フィールドを挿入します。

f:id:tetsutalow:20181210092129p:plain

投票用コードを挿入したところ

必要であればプレビューした方が分かりやすいですね。

 

f:id:tetsutalow:20181210100459p:plain

差し込みフィールドのプレビュー

つぎにQRコードの挿入です。これは「バーコードフィールドの挿入」で行います*12。これをクリックすると挿入するフィールドとバーコードのタイプが選べますが、今回埋め込もうとしているようなURLだと文字数が多いので、フィールドを選択すると自動的にバーコードのタイプとしてQRコードが選択されます。

f:id:tetsutalow:20181210104616p:plain

QRコードを挿入しようとすると…

ただ、プレビューの時点で気づくと思うのですが大きすぎるのですよね。QRコードの大きさは文字数に比例しちゃうので、URLが長いとどうしても大きくなります。プレビューの大きさは実際の埋め込みの大きさなので、これがそれなりに小さくなるまで「詳細設定」で調整した方がよいです。

f:id:tetsutalow:20181210111446p:plain

QRコードのサイズ調整

まず、エラー修正のデフォルトがQ(25)になっていますが、よほどプリンタや用紙がダメでなければM(15)くらいでよいと思います。スケールはうちの環境だと経験上50%くらいまでは平気ですが、小さくしすぎるとスマホでも読めなくなってしまうので、実際に印刷して試しながら小さくなりすぎない程度にした方がよいでしょう。

挿入後は実際にレイアウトが崩れないかどうかを「結果のプレビュー」で確認します。大きすぎるときは、バーコードの上で右クリックして「バーコードの編集」を選べば上記画面に戻れます。

f:id:tetsutalow:20181210112437p:plain

QRコードが大きくなりすぎたら

f:id:tetsutalow:20181210112801p:plain

投票用紙1枚分が完成!

うまく収まったらこれを複製します。まず大事なことは、差し込み印刷で1枚の用紙に複数のレコードを印刷するときには「ルール」を使って、次のレコードへの移行を促す「Next Record」フィールドを埋め込まないといけません。そのために、まず「結果のプレビュー」をオフにします(重要)。そうしないとこのフィールド、見えないので。

QRコードの続きに、≪Next Record≫を埋め込むのですが、これがとてもわかりにくいアイコンなのです…「差し込み文書」タブで現れるリボンの「文書入力とフィールドの挿入」の右上の、小さな?がついたアイコンです。

f:id:tetsutalow:20181210114413p:plain

Next Recordの挿入

うまくいったら、これを残りの7つのセルにコピペします。

f:id:tetsutalow:20181210115751p:plain

コピペして8枚に展開する

大事なのは、最後の≪Next Record≫は削らないといけないことです。というのは、差し込み印刷では1枚の印刷が終わったら自動的に次のレコードに進んでしまうので、最後に≪Next Record≫が残っているとそのレコードがスキップされ、印刷されないレコードが出てしまいます。

完成した投票用紙はこうなりました(ここでは「結果のプレビュー」を有効にしています)。

f:id:tetsutalow:20181210140246p:plain

完成した投票用紙

念のため、1枚だけ先に印刷してQRコードが正常に読み取れるかチェックした方がいいでしょう。試しに投票して、先に指定したGoogle Spreadsheetに集計結果が反映されるのを確認してもいいでしょう。一度投票しても、集計のGoogle Spreadsheetの該当行を消去すれば、集計結果をキャンセルできます。

読み取ることができたら、「完了と差し込み」を押して、差し込み印刷して(1000件なら125枚ですね)裁断機などで切り分ければ投票用紙の完成です。これを投票する人に配って処理すれば、投票の集計はできるようになります。参考までに、私の方で作ったこの投票用紙のWordファイルを置いておきます。

きのこたけのこ投票用紙.docx - Google ドライブ

きのこたけのこ 投票用紙(差込後).docx - Google ドライブ

これで完成?

一応この状態までくれば、投票結果を集計することまでは可能です。無効投票か、2重投票のチェックは、集計後のスプレッドシート上で投票用コードを確認すればいいでしょう。

…ただそれではつまらないですよね。それに面倒です。無効なコードによる投票や2重投票のチェックはできればその場でやりたいものです。そこでGoogle App Scriptで無効票をリアルタイムチェックします。

今回は、次のようなスクリプトを作ります。

  1. Googleフォームから回答集計用のGoogleスプレッドシートに回答が送信され、集計用スプレッドシートに1行追加が行われたときにそれをトリガに起動する。
  2. 集計用スプレッドシートは、回答で書き込まれた投票用コードが、有効な投票用コードが並んだスプレッドシートに含まれているか検索する。見つからなければ不正コードなので、集計用スプレッドシートの当該行にエラーを表すEを書き込む。
  3. 有効な投票コードが見つかれば、すでに使用して無効にされているかどうかをチェックする。無効にされている場合にはそのスプレッドシートの該当する投票用コードの列にXが書き込まれており、そうでなければ空白であるはずなので、そのセルの内容を投票集計用シートにコピーする。さらに投票コードを無効にするため、投票用コードの該当行にXを書き込む。

手順は以下の通りです。まず、先ほどの投票用コードが含まれるExcelシート(ここでは「投票用コード.xlsx」)を、Googleフォームと同じアカウントのGoogleドライブにアップロードしてしまいます。さらに、これをGoogleスプレッドシートとして開きます。ここでC列に、投票に使用された投票用コードにマークをつけるべく見出し行をつけます。

f:id:tetsutalow:20181210165940p:plain

投票用コード一覧で重複チェックの準備

さらにURLを見てスプレッドシートのIDを取得します。URLは、https://docs.google.com/spreadsheets/d/<スプレッドシートID>/という形式なので、これをメモしておきます。

次に投票フォームの「回答」タブから集計用のスプレッドシートを開きます。緑色のスプレッドシートのアイコンが目印です。

f:id:tetsutalow:20181210155649p:plain

Googleフォームから回答を集計するスプレッドシートを開く


 開いた回答集計フォームの回答に続く列を、不正投票や二重投票をメモする列にしましょう。下記の場合はD列ですので、適当に見出しを付けます。

f:id:tetsutalow:20181210160519p:plain

不正や二重投票を記録する列に見出しを付ける

ではいよいよスクリプトを。この集計フォームを開いた状態で「ツール」メニューから 「スクリプトエディタ」を開きます。そこに、myFunctionのスケルトンが表示されますが、その代わりとしてこのコードを貼り付けます。

投票集計のためのGoogle Apps Script

このうち4行目のSpreadsheetApp.openById()のID部分を、上で取得した投票用コードのスプレッドシートのIDと入れ替え、getSheetByName('codes')のcodesも該当シート名で入れ替えておいてください。また、プロジェクト名が「無題のプロジェクト」になっていると思うので、これを適当に変えます。ここでは「投票コードチェック」としました。

コードとしてはそれで準備OKなのですが、さらに2つ設定が必要です。まずこのコードがスプレッドシートを書き換えられるように権限を渡さないといけません。これ面倒なので、乱暴ですがその権限が必要な部分を無理やり実行します。具体的にはcodecheck()を引数もなしに実行しちゃいます。

f:id:tetsutalow:20181211134431p:plain

codecheck()を無理やり実行して権限取得画面を出す

 

すると次のような画面になります*13

f:id:tetsutalow:20181211135913p:plain

権限の付与

するとこんな画面になります。

f:id:tetsutalow:20181211141157p:plain

権限付与しようとすると…

なかなかおどろおどろしいですが、このスクリプトに不用意に権限付与するとGoogleドライブ上のデータを書き換えられてしまうのでかなり慎重な手順になっています。要するに自分が何をやっているかわかってない人はクリックしてはいけないってことでしょう。「詳細」「<<プロジェクト名>>に移動」をクリックすると、こんな画面になります。

f:id:tetsutalow:20181211141859p:plain

権限付与画面

Google Apps Scriptの場合はOAUTHを権限管理に使ってるので、OAUTHを使うサービスをよく使う人にはおなじみの画面になりました。これを使って先ほどのプログラム(を含むプロジェクト)にGoogleドライブ内のスプレッドシートへの編集権限を付与します。すると直ちに先ほどの関数codecheck()が走り、引数が空なのでエラーで止まりますが、権限付与はできました。

次に、codecheck()が動作するトリガを設定します。スクリプト編集の画面から「編集」「現在のプロジェクトのトリガー」を選びます。

f:id:tetsutalow:20181211142901p:plain

現状はトリガーがないので追加します。

f:id:tetsutalow:20181211143119p:plain

トリガーを追加する

トリガーは、フォームの送信をトリガとしてcodecheck()が起動するようにします。

 

f:id:tetsutalow:20181211143647p:plain

追加するトリガを設定

これで保存すれば動くはずです。やってみましょう!

f:id:tetsutalow:20181211151827p:plain

投票が集計される様子

f:id:tetsutalow:20181211152523p:plain

投票用コードが消費される様子

今回の投票集計フォームについても閲覧可能にしておきますので、上記の投票用コードのスプレッドシートでまだ使われていないものを探して、https://bit.ly/KinokoTakenoko に入力してみて動きを観察してみてください。

docs.google.com

CSSx2.0 in CSS2018での利用結果

このシステム、だいたい構築に半日(午後いっぱい、というイメージ)という短時間でほぼ構築できた(一番時間がかかったのは投票用紙のレイアウトと印刷・裁断)というお手軽システムの割にはうまく動かせたと思います。CSS2018ではこれをつかって集計しましたが、その結果の概要は以下の通りです。

  • 総得票数:207票
  • うち紙で投票されたもの:4票
  • 有効投票数:191票
  • 無効コードによる投票:4票
  • 重複投票:12票(同一コードによる2回投票5、3回投票2、4回投票1)
  • 最高10秒間に12票、5分間に71票を処理

まぁ性能としてはこの規模なら十分かと思います。ただ、残った課題もありまして…

まず、Googleフォームで投票完了時、重複投票や無効な投票用コードによる投票を注意するようなメッセージを出したいのですが、この部分に出るメッセージは動的に変更できない*14のでできません。つまり、自分がその投票用コードを使って投票したかどうか思い出せないような人はもう一度投票するしかないわけですが、その投票が実際に重複だったのかどうかを確かめる方法がないのです。これはGoogleフォームの制限なので、他のなにかよいシステムで作ればいいのですけど、Googleフォームの手軽さと性能の高さ、堅牢さはなかなか得難いものがあるので、まぁ「簡易なシステム」なのでご勘弁くださいというところでしょうか。

もう一つの課題は集計です。とはいえ、エラーチェックと重複チェックは終わっているので、集計スプレッドシートをダウンロードしてExcelでちょっと作業すれば集計できるのですが、そこもGoogle Apps Scriptで自動化してしまいたいなと思ってます。これはもう少し頑張ればできる程度のコーディング量なので*15、また暇をみてやってみたいと思っています。

12月15日追記

暇じゃないのに逃避でやっちゃった…集計用のシートを加えるならすぐできるなと思ってしまい。

投票集計のためのGoogle Apps Script(Ver.2)

おわりに

コーディングという意味ではほんの少しだったのにblogにまとめると思ったより大作になってしまいましたけど、「投票」っていうものをもし管理する必要にかられた方がいたら、何かのお役に立つでしょうか。

さて、Advent Calendar10日目の担当はnakarioくんです。といっても、もう記事が出ていますね。

nakario.hateblo.jp

超人ロック!私が学生だった30年以上前はもちろん、そのさらに前から40年近く、KMCで盛んに遊ばれてきたゲームです。超人ロックという作品は根強いファンがいますが、このゲームがこんなに長く遊ばれてるコミュニティはKMCぐらいじゃないかと思います。是非記事を読んでその魅力に触れてみてください!

KMCM

KMCは、年齢所属居住地など問わず誰でも入部できます。実際現役女子高生もいれば私みたいなおっさんもいますし、京都周辺に限らず東京にも九州にも部員がいます 。コンピュータを使って「何か」をしたい人は是非ご連絡を。

www.kmc.gr.jp

また、もうすぐ平成最後のコミケですが、この冬もKMCは日-東タ31aに出ていますのでお立ち寄りください*16。Webカタログにアクセスできる方は、こちらへどうぞ

いじょ。

*1:予約Tweetを使って、素数日当日の夜中に呟くように設定をしています。

*2:まだ煮詰まっていない研究の紹介や、場合によっては冗談のような発表を集めたセッションで、よく夜に行われる。CSSの場合にはネタ色が強いです。

*3:ネタはマイナンバーのチェックデジットがおかしい話でした

*4:なぜかEdgeでは動かないようですが…そういやEdgeもChroniumベースになるんですねぇ

*5:英大文字の文字コードが65から90であることを利用してCHAR( RANDBETWEEN(65,90) )を文字数だけ繰り返してるだけです

*6:26^{10}のものから1000個選ぶ時の重複の確率はだいたい1-e^{-(1000*999)/2*26^{10}}なので10億分の3.5くらい。

*7:直接csvでダウンロードすることもできるが文字コードがUTF8なので日本語の見出しが文字化けしてしまう

*8:あの点3つとか線3本のメニューアイコンの正式名ってあるんですかね?欧米人はkebabとかburgerと呼んでるようですが…

*9:よくレイアウトがわからなくなるという話もありますが、あれは図表に「アンカー」というものが位置決めのために存在していることがわかれば使いこなせるようになります。ただそのアンカーが、実にWordのシステムとしての構造の都合で決まっているものなので、普通の人には評判悪いのでしょう。プログラマとしては理解できる方法なので受け入れられるのですが。

*10:この「宛先」という表現が分かりにくいのですが、住所録(Address Book)のことのようです。要は差し込み印刷の元データなら別に住所録相当のものでなくとも選択すればよいのです。

*11:ここで「差し込み印刷の開始」を選びたくなりますが、無駄なこといっぱいやってくれるので使わない方がマシです…私はまず使わなくなりました

*12:余談ですが、このバーコードフィールド、私は特に1次元バーコードを良く活用しています。1次元バーコードのリーダが安いので(今や3000円ほどです)、例えば学生に配る小テストは回答用紙に学籍番号と名前を印刷しておいてものを配って、回収後これをバーコードリーダで読み取って集計するExcelマクロを組んで処理したりしてます。QRコードは最近、スキャンデータをPythonで読み取って処理するのを始めてますが、手軽さでは1次元バーコードの方がずっとよいですね。

*13:個人向けのGoogleアカウントとGsuitesアカウントで少し違うようですが、ここでは個人向けGoogleアカウントの例です

*14:おそらくセキュリティを担保するのが難しいからだと思います

*15:今回は、投票を数えた結果をさらに別のスプレッドシートにまとめるほうがよいけど面倒だな、という理由でやめました

*16:私もKMCブースでないどこかにいると思います