2020年5月13日水曜日

簡易SNSを作ってみよう(12)

新着アップロードの対応
Teacherロールでログインしたときに,新着アップロードが分かるように修正する.
アップデート順に並べるように変更
生徒の並びをアップデート順番に並べるように変更する.

【手順】
vi app/controllers/users_controller.rb
(以下を修正)
class UsersController < ApplicationController
  before_action :authenticate_user!

  def show
    @user = User.find(params[:id])
    @students = User.where(role: 'student')
.order('updated_at desc') if @user.role == 'teacher'                               
    @posts = Post.where(user_id: @user.id).order('created_at dssc')
  end
end
メッセージがポストされたときの処理を変更
Teacherロール以外でメッセージがポストされたときにUserのエントリをアップデートするようにする.すなわち,新たに生徒・学生がメッセージをポストしたときは,エントリがアップデートされるため,Teacherロールでログインしたときに先頭に表示されるようになる.
なお,Teacherロールでログインして書き込んだときには,Userエントリは更新されないため,並び順は不変となることに注意されたい.

【手順】
vi app/controllers/posts_controller.rb
(以下を追加)
  def create
    p = post_params
    user = User.find(p[:id])
    if (p[:body] == "")
      flash[:alert] = 'Null comment is not permitted.'
    else
     if user.posts.create(body: p[:body], submitter: current_user.id)
        user.touch if current_user.role != 'teacher'
        flash[:notice] = 'Post was successfully created.'
      else
        flash[:alert] = 'Something went wrong'
      end
    end

    redirect_to user_path(user.id)
  end

Visitモデルの作成
各ページへの参照状況を表すモデルとしてUserモデルに紐づくVisitモデルを作成する.dependent属性を付け,ユーザーが削除されたときはそれに紐付いているVisitのエントリは全て削除されるようにする.
【手順】
bin/rails g model visit user_id:integer visitee:integer
bin/rails db:migrate
vi app/models/user.rb
g(以下を追記)
class User < ApplicationRecord
  has_many :posts, dependent: :delete_all
  has_many :visits, dependent: :delete_all

…(略)…
end

vi app/models/visit.rb
(以下を追記)
class Visit < ApplicationRecord
  belongs_to :user
endTeacher

ページ参照の作成と更新
各ページを参照した記録を残すようにする.current_user.visits.find_by(...) という書き方 current_user.visits << Visit.create(...) という書き方に注意.
vi app/controllers/users_controller.rb
(以下を追記)
 def show
   @user = User.find(params[:id])
   @students = User.where(role: 'student')
.order('updated_at desc')
   @posts = Post.where(user_id: @user.id)
.order('created_at desc')

   visit = current_user.visits.find_by(visitee: @user.id)
   if (visit != nil)
     visit.touch
   else
     current_user.visits << Visit.create(visitee: @user.id)
   end
 end

オンライン授業と教育効果

オンライン講義が本格的に稼働し始めた大学も多いようで,LMSにアクセス集中でサーバダウンだとかの阿鼻叫喚なコメントも,まだ,ちらほら届いている.本ブログでも指摘したように,4月のアタマに東大や立命館大が先陣を切ってトラブルを示してくださったのを反面教師にできなかったのだろうか?という疑念も残るものの,まあ,本学もそれなりにヤバい状況 ※ だったようなので,あえてここで批判することはしない.

さまざまな対処を経てなんとか無事にスタートを切ることができたという大学の報告も耳にするので,そのような経験は皆で共有して,今後に備えたいものですね.

学生の反応と学習のあるべき姿

ところで,本格的なオンライン教育がスタートして学生の反応をみていると,「課題が多くてたいへん!」という悲鳴をちらほら耳にするようになった.「たいへんなのはその課題にいちいちフィードバックしなきゃならない教員も同じだよ!」と主張?したい気持ちを押さえ,たしかにオンライン講義で「課題を与えてフィードバックせえよ」という文科省様のご指導もあり,おしなべて,そんな状況になっているようである.

「対面授業だったらさー,教室に行って寝てればよかったのにさー」というフトドキな声は,この際,無視するとして,たしかに,教員も大変なら学生も大変な状況かもしれない.

しかし,これ,俯瞰でみてみれば,あるべき姿に近づいているのではなかろうか.今回のオンライン対応のよいところは授業動画などの教材が溜まっていくことなので,今後,反転授業方式に対応するいいきっかけになったのではないかと,私も前向きに捉えて作業を進めている.それと同じように,学生も「予習・復習をきっちりする」という習慣付けをするいい機会になるのではなかろうか.どうだろう?

あとは,量の問題をなんとかする必要があるかな.全ての先生が張り切っちゃうと,学生の負荷も相当なものとなってしまいそう.まあ,それに耐えられる学生が真の大学生だ!と突き放すのは簡単ではあるが.

学生の反応をきいて,そんなことを考えた次第.下の絵は「夏休みの宿題が終わらない男の子のイラスト」だって!いらすとや,何でもあるなあw


【脚注】
※ 本学の場合,学事日程の関係上,理工学部が1日はやく開始して,そこでトラブルがあまり出なかったので油断した?まあ,個別の反省については落ち着いてからおそらくしかるべき人が総括してくださることでしょう.

2020年5月11日月曜日

ヒルベルト曲線を描く

JavaScriptでHTMLキャンバスにヒルベルト曲線を描くプログラムです.

このプログラムのキモはこちら.中央大学国際情報学部の1年生向け科目「プログラミングのための数学」で解説しています.




より詳しく知りたい方は「飯尾淳,連載:バーティカルバーの極意,シェルスクリプトマガジン vol.65, pp. 74-78, 2020年3月25日」で解説しているので,そちらをご参照ください(雑誌で解説しているバージョンは,誌面の関係からアニメーションしません).

const MAX_COUNT = 8;

// the canvas and its graphic context
var cs  = document.getElementById('theCanvas');
var ctx = cs.getContext('2d');

// line style
var colors = [ 'gray', 'navy', 'purple', 'brown', 
  'red', 'orange', 'yellowgreen', 'skyblue' ];
var widths = [5, 4, 3, 2, 2, 1, 1, 0.5 ];

var tm = [
  [ [  0,  1/2,   0], [ 1/2,   0,   0], [0, 0, 1] ],
  [ [1/2,    0,   0], [   0, 1/2, 1/2], [0, 0, 1] ],
  [ [1/2,    0, 1/2], [   0, 1/2, 1/2], [0, 0, 1] ],
  [ [  0, -1/2,   1], [-1/2,   0, 1/2], [0, 0, 1] ]
]

var E = [ [ 1, 0, 0], [0, 1, 0], [0, 0, 1] ];

function affine_transform(m, p) {
  return [ m[0][0] * p[0] + m[0][1] * p[1] + m[0][2],
       m[1][0] * p[0] + m[1][1] * p[1] + m[1][2] ];
}

function mat_mul(m0, m1) {
  return [ [m0[0][0]*m1[0][0]+m0[0][1]*m1[1][0]+m0[0][2]*m1[2][0],
            m0[0][0]*m1[0][1]+m0[0][1]*m1[1][1]+m0[0][2]*m1[2][1],
            m0[0][0]*m1[0][2]+m0[0][1]*m1[1][2]+m0[0][2]*m1[2][2]],
           [m0[1][0]*m1[0][0]+m0[1][1]*m1[1][0]+m0[1][2]*m1[2][0],
            m0[1][0]*m1[0][1]+m0[1][1]*m1[1][1]+m0[1][2]*m1[2][1],
            m0[1][0]*m1[0][2]+m0[1][1]*m1[1][2]+m0[1][2]*m1[2][2]],
           [m0[2][0]*m1[0][0]+m0[2][1]*m1[1][0]+m0[2][2]*m1[2][0],
            m0[2][0]*m1[0][1]+m0[2][1]*m1[1][1]+m0[2][2]*m1[2][1],
            m0[2][0]*m1[0][2]+m0[2][1]*m1[1][2]+m0[2][2]*m1[2][2]] ];
}

function hilbert(n, m) {
  if (n > 0) {
    tm.forEach(mm => hilbert(n-1, mat_mul(m, mm)));
  } else {
    [ [0.25, 0.25], [0.25, 0.75], [0.75, 0.75], [0.75, 0.25] ]
     .map(p => affine_transform(m, p))
     .map(p => [p[0]*cs.width, p[1]*cs.height])
     .forEach(p => ctx.lineTo(p[0],p[1]));
  }
}

function drawHilbert(i) {
  ctx.beginPath();
  ctx.lineWidth   = widths[i];
  ctx.strokeStyle = colors[i];
  hilbert(i, E);
  ctx.stroke();
}

function doLoop(maxCount, i) {
  if (i < maxCount) {
    drawHilbert(i);
    setTimeout(function() {
      doLoop(maxCount, ++i) }, 1500);
  } else {
   ctx.clearRect(0, 0, cs.width, cs.height);
   doLoop(MAX_COUNT, 0);
  }
}

doLoop(MAX_COUNT, 0);

2020年5月10日日曜日

WordやPagesに数式を書き込むやり方

最近のワープロやプレゼンソフトでは,数式をLaTeXの書式で表現して張り込むことができるようになっているようです.そのやり方を簡単に解説します.

MS Word編

Microsoft Wordに数式を貼り付ける方法を説明します.まず,数式を入れたいところにカーソルを持っていきましょう.その位置で,挿入タブをクリックし,「数式の挿入」ボタンを押します.すると,数式エディタが挿入されます.

数式のLaTeX表現を書き込んだら,エンターキー(リターンキー)で入力を確定させましょう.数式を入れ込むことができたことを確認してください.

ExcelやPowerPointでも同様の操作で数式を入れることができるようですが,若干,操作方法が異なるようです.いろいろ試してみましょう.

数式エディタのなかで,表現したい数式を入れていきます.上のボタンを使ってGUI方式で入力しても構いませんが,LaTeX書式による数式の表現が使えます.次の図は,ディリクレ関数を表現したものです(なお,「\」が「¥」マークになっているのは,文字コードの都合上です.見た目は若干違いますが,同じです).

Pages編

Macを使っている人は,PagesやNumbers, Keynoteでも,同様にLaTeX書式を用いて数式を表現することができます.Wordでの説明と同じように,数式を入れたいところにカーソルを持っていきます.「挿入」メニューから「方程式…」を選びましょう.

エディタで数式を編集します.内容は同じです.

書けたら「挿入」ボタンをクリックすれば,数式を書類に入れ込むことができます.やってみましょう.

2020年5月9日土曜日

manabaのリッチテキストエディタで数式を書くやり方

以下,せっかく学生用マニュアルを作ったのに,manabaのマニュアルをよく見たら「数式エディタを使えるのは教職員だけ」!との記述がありました.orz ... よよよよ

以下は,一部,適切ではない情報を含みますのでご注意ください.

manabaをお使いになっていて学生と数式のやりとりをする必要に迫られている先生方へ.

manabaのリッチテキストエディタではMathJaxを使った数式の記述ができるようですが,残念ながらその使い方が教員用マニュアルにしか記載されておらず,学生向けの説明がありません.そこで,学生向けの説明文書を作りました.

使い方としては,テキスト記述型のレポート課題提出で数式混じりのレポートを提出させるケースを想定しています.コメントはリッチテキストを書き込めるため,コメント欄を使って書き込んでもらおうというアイデアです.このやり方だとあとでまとめてダウンロードしたときにうまく扱えないかもしれない?という課題は残されているものの(未検証です),当座のやりとりとしてはこれで十分かなと考えています.

学生向けガイド文書(8ページほどのPDFです.ダウンロードしてご利用ください)

端末共有によるオンライン・ペアプログラミング

オンライン演習のやり方のひとつとして,学生の端末を共有したペアプログラミングを実施している.これがなかなか調子がよい.エラーが出ても,全てがこちらに筒抜け.だいたいどこで躓くかわかるから,チャットも併用して,「〇〇ってコマンド打ってみてごらん」「何行目が違ってるよ」みたいな指導ができる.

難点は,「そこ間違ってる」みたいな指示語が使えないところか.まあ,それはオンライン講義で注意しようという項目で一般的な話題かも.

このやり方がうまくいっているのは,今年は院生が1名しかいないから,マンツーマンで贅沢なゼミをしているからだなあ.複数人に対してこのやり方は通用しなさそう.いちいち画面共有を切り替えないといけないので,できても数名だろうな.画面共有,複数人の画面を一度に共有できるようなオンラインコミュニケーションツールは無いものだろうか?作っちゃう?

あと,これって業務でも適用できそう.ペアプログラミングって非効率そうでけっこう有効だと思うんだけど,オンラインでも,このやり方で,ペアプログラミングできるよね?

2020年5月7日木曜日

「「「〇〇チャレンジ」への批判」に対する反論」への再批判

自粛生活で皆さんヒマを持て余しているのか,最近,ブックカバーチャレンジだのビールチャレンジだの,「みんなの好きな〇〇を紹介しよう.このバトンをX人に回そう」的なアレが流行っている.結論から言う.これはチェーンメールの一種である.したがって,ホイホイ乗っかる前に,考えねばならないことがある点をきちんと理解しておくべきである.

A: 「〇〇チャレンジ」への批判

まずは,ここから始めたい.「〇〇チャレンジ」はチェーンメールの一種である.それについては異論はなかろう.チェーンメールの定義にそのまま当てはまっている.違うとすれば,媒体がメールじゃなくてSNSのメッセージであるというくらい.

そして,「〇〇チャレンジ」はチェーンメール的なものだから,よくない!という批判がある.私も積極的に批判するものでもないが,あまりヨシとはしない立場を取る(その理由が本稿の趣旨).

B: Aに対する反論

そのような批判に対して,チェーンメールや不幸の手紙は,デマを撒き散らしたり,人を不安にさせることで社会的な混乱の元になるからよくないであって,「〇〇チャレンジ」はそれらとは違う!という反論がある.人を楽しませるものだから,いいじゃないか!との主張である.

たしかに,いま流行っているいろいろなチャレンジ,それから,ちょっと前に流行ったアイスバケツチャレンジ,そのようなものは,いわゆるこれまでのチェーンメールや不幸の手紙で語られるような内容ではない.しかし,不幸の手紙はさておくとしても,子どもたちの間でときどき流行る恋愛モノのチェーンメールだって,内容は他愛のないものであり,それをもって批判への反論材料にするのは少し弱い.

その他,仲間はずれが出るからダメなんだ,いやそんなの単に人間関係の問題じゃないか,とか,時間を削がれるのが問題だ,そんなのたいした時間じゃないだろ,とか,いろいろとAに対するB的な反論は主張されているが,いずれも,そうともいえるしそうでないともいえる的な議論がなされているようで,ここでは放っておくことにしたい.

C: Bに対する再批判

さて,ではここで,本稿の趣旨である,「『人を楽しませる内容なんだから,よいだろう?』に対する反論」を試みよう.

そもそも「人を楽しませる内容である」というところをまずは疑っていただきたいのである.面白いと思っているのはあんたたちだけなのよ(あんたたちだけかもしれないのよ)?という状況をぜひとも考えていただきたい.さらに,これは,人間関係が絡んでいて下手に断れない,というオマケも付く.

そして,それをX人に回す,しかもX>1であるという点が最大の問題なのだ.新型コロナウイルス騒動で「実効再生産数」という言葉を耳にした人も多いことだろう.Xが1より大きいと,感染は指数関数的に拡がっていく.チェーンメールも同様で,特定の価値観がじわじわと拡がっていく.ああ,考えるだに恐ろしい.

話を簡単にするために「ブックカバーチャレンジ」で考えてみよう.読書習慣を拡めようという考えには私も賛成である.ただし,その拡散方法として,チェーンメール的なやり方が妥当か否か.ぜひ,考えてみていただきたい.

というわけで,私は「次の人へ回す,なら,まあヨシ(X = 1 なので不必要には拡散しない.よって許容範囲)だが,適切とは考えにくい手法(ねずみ講的手法)で特定の価値観をばら撒くな」という点で,〇〇チャレンジにはいささか問題があると考えている.

2020年5月6日水曜日

簡易SNSを作ってみよう(11)

見栄えの修正(2)
メッセージ表示部に,dismissボタンを付けて,読んだら消せるようにしよう.
styleタグによるこの設定は使えない.dismissボタンを付けることによって,メッセージがないときでもemptyではなくなってしまうから.従って,この部分は削除する.

【手順】
vi app/views/layouts/application.html.erb

    <style>
      .alert:empty {
         display: none;
      }
    </style>

上記の部分を削除する.そのかわり,メッセージ表示部を次のようにする.

   <% if notice %>
     <div class="alert alert-info alert-dismissible fade show"
role="alert"><%= notice %>
       <button type="button" class="close" 
data-dismiss="alert" aria-label="閉じる">
         <span aria-hidden="true">&times;</span>
       </button></div>
   <% end %>

   <% if alert %>
     <div class="alert alert-warning alert-dismissible fade show" 
role="alert"><%= alert %>
       <button type="button" class="close" 
data-dismiss="alert" aria-label="閉じる">
         <span aria-hidden="true">&times;</span>
       </button></div>
   <% end %>