投稿者: uep

  • MoodleのCalendarをGoogle Calendarにエクスポートで「終日」の扱いは?

    Moodleに研究室の予定を書き込んでいるが、終日の予定は時刻をデフォルトの「00:00」のままで変更しない。特に終了時刻はわざわざ入力しない。これで「終日」になることを期待するが…。

    特に意識しなければ日付の「時刻」が「00:00」になっており、これで終日になると思ってしまう
    特に意識しなければ日付の「時刻」が「00:00」になっており、これで終日になると思ってしまう

    これをGoogle Calendarにエクスポートすると、前日の終日予定に見えてしまう。これを回避するためには、00:00以外のそれより遅い時刻に設定すればよい。

    たしかに00:00になっているが、日付の境目にイベントが発生し、表示上は…。
    たしかに00:00になっているが、日付の境目にイベントが発生し、表示上は…。
    前日の終日予定に見えてしまう
    前日の終日予定に見えてしまう
  • Emacs24.5 新しいフレームでフォントが違うのを修正

    環境はEmacs 24.5, Windows10である。init frameをメイリオで設定しているのだが、C-x 5-2で新しいフレームを開くとこんな風になる…。

    frame-fonr-emacs24.5
    フレームごとにフォントが番う例

    そこで、MewやFiremacsで余りに有名な山本和彦さんの記事を参考に修正!山本さんありがとうございます。

    [code];; C-x 5 2 で新しいフレームを作ったときに同じフォントを使う
    (setq frame-inherited-parameters ‘(font tool-bar-lines))
    [/code]

  • LMSログとマイニングツール/概念あれこれ

    前々から行いたかった、LMSに蓄積されているログを対象データとした研究について。

    行いたいことはテキストマイニング(これはこれで「重要文抽出」「キーワード抽出」「トピック抽出」「テキストの一貫性評価」「複数文書要約」「テキストクラスタリング」などの面白いトピックがある)ではない。LMSで提供しているSCORMコンテンツの改善を目的とし、データベースなど構造化されたものから、ユーザに着目した分析となるであろう。データマイニングと言えるかもしれない。たとえば、BovoらEDM2013ICEEE2013でユーザそれぞれについてのログイン回数、最終ログイン、学習時間、レッスン読了数、ダウンロード数、小テスト、課題の評定と各種平均を正規化したデータをWekaでクラスタリングしている。

    Wekaについては、恩師である渡邊裕司先生もお使いであると仰っていた、それなりに実績のあるツールのようだ(OERもある)。森幹彦先生には、orangeというビジュアライズされたワークフローを作成できるPythonベースのツールを紹介していただいた(活用している方のブログ記事)。また、これらのツールを比較した解説もある(これとかこっちとかスライドも)。

    ただし、ツールは夢のようなものではなく、それが何を行っているのか理解できない者が使うべきではない。当たり前だが、ツールを使うことが目的になってはならない。最終目的はコンテンツの改善である。ただ、ログなんぞから、ユーザの「学習」状況など分かるはずがない。しかしながら、全てをきちんと受講している「可能性」のある閲覧状態というのはあるはずである(受講していてもタレ流しかもしれないから)。

    1. SCO単位の受講率(というのか?)
    2. 各SCOの所要時間以上で受講している割合(クエリがちょっと難しいかもしれないが分かれば面白い)

    SCO単位の受講率と総合テストの成績の相関は容易に分かる。これに加えて上記2が分かれば、オンラインかつモチベーションがない、強制的にやらされる「○○○○についての学習」というシチュエーションで、ユーザの「飽き」と「作業ゲー状態」を検出することができるかもしれない。また、たとえば次のようにユーザを分類し、アダプティブなコンテンツとすることも考えられる。

    1. まじめに受講した結果成績が良い
    2. そもそもICTスキルが高く、受講せずとも成績が良い
    3. それ以外、また他の分類

    決してバズワードの研究分野のつもりはありませんから!

  • Moodleのログを解析向けに出力するカスタマイズ

    と言っていいものか分からないが、行ったことをまとめておく。大したことはやっていない。SCORM受講ログの取得に十時間以上かかってしまったし、コースログの取得はPHPのmemory_limitとのたたかいであった。やはりPHPはパフォーマンスの問題がある。Try & Error の開発がしやすいこととのトレードオフなのだろうが…。

    1. ユーザ名を特定困難、識別可能な内部IDで出力する
      [code]— course/lib.php.20151020 2015-10-20 11:26:45.000000000 +0900
      +++ course/lib.php.20151016 2015-10-16 19:34:45.000000000 +0900
      @@ -424,7 +424,7 @@
      $link = new moodle_url("/iplookup/index.php?ip=$log->ip&user=$log->userid");
      $row[] = $OUTPUT->action_link($link, $log->ip, new popup_action(‘click’, $link, ‘iplookup’, array(‘height’ => 440, ‘width’ => 700)));

      – $row[] = html_writer::link(new moodle_url("/user/view.php?id={$log->userid}&course={$log->course}"), $log->userid);
      + $row[] = html_writer::link(new moodle_url("/user/view.php?id={$log->userid}&course={$log->course}"), fullname($log, has_capability(‘moodle/site:viewfullnames’, context_course::instance($course->id))));

      $displayaction="$log->module $log->action";
      if ($brokenurl) {
      @@ -531,7 +531,7 @@
      $link = new moodle_url("/iplookup/index.php?ip=$log->ip&user=$log->userid");
      echo $OUTPUT->action_link($link, $log->ip, new popup_action(‘click’, $link, ‘iplookup’, array(‘height’ => 400, ‘width’ => 700)));
      echo "</td>\n";
      – $fullname = $log->userid;
      + $fullname = fullname($log, has_capability(‘moodle/site:viewfullnames’, context_course::instance($course->id)));
      echo "<td class=\"r$row c3\" >\n";
      echo " <a href=\"$CFG->wwwroot/user/view.php?id={$log->userid}\">$fullname</a>\n";
      echo "</td>\n";
      @@ -619,7 +619,7 @@

      $coursecontext = context_course::instance($course->id);
      $firstField = format_string($courses[$log->course], true, array(‘context’ => $coursecontext));
      – $fullname = $log->userid;
      + $fullname = fullname($log, has_capability(‘moodle/site:viewfullnames’, $coursecontext));
      $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
      $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.’ ‘.$log->action.’ (‘.$actionurl.’)’, $log->info);
      $csvexporter->add_data($row);
      @@ -730,7 +730,7 @@
      $myxls->write($row, 0, format_string($courses[$log->course], true, array(‘context’ => $coursecontext)), ”);
      $myxls->write_date($row, 1, $log->time, $formatDate); // write_date() does conversion/timezone support. MDL-14934
      $myxls->write($row, 2, $log->ip, ”);
      – $fullname = $log->userid;
      + $fullname = fullname($log, has_capability(‘moodle/site:viewfullnames’, $coursecontext));
      $myxls->write($row, 3, $fullname, ”);
      $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
      $myxls->write($row, 4, $log->module.’ ‘.$log->action.’ (‘.$actionurl.’)’, ”);
      @@ -844,7 +844,7 @@
      $myxls->write_string($row, 0, format_string($courses[$log->course], true, array(‘context’ => $coursecontext)));
      $myxls->write_date($row, 1, $log->time);
      $myxls->write_string($row, 2, $log->ip);
      – $fullname = $log->userid;
      + $fullname = fullname($log, has_capability(‘moodle/site:viewfullnames’, $coursecontext));
      $myxls->write_string($row, 3, $fullname);
      $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
      $myxls->write_string($row, 4, $log->module.’ ‘.$log->action.’ (‘.$actionurl.’)’);

      — mod/quiz/report/attemptsreport.php 2015-10-16 19:03:12.000000000 +0900
      +++ mod/quiz/report/attemptsreport.php.20151016 2015-10-16 19:04:44.000000000 +0900
      @@ -153,10 +153,10 @@
      $headers[] = ”;
      }
      if (!$table->is_downloading()) {
      – $columns[] = ‘userid’;
      + $columns[] = ‘username’;
      $headers[] = get_string(‘name’);
      } else {
      – $columns[] = ‘userid’;
      + $columns[] = ‘username’;
      $headers[] = get_string(‘name’);
      }

      — mod/scorm/report/interactions/report.php.20151020 2015-10-20 11:21:52.000000000 +0900
      +++ mod/scorm/report/interactions/report.php.20151016 2015-10-16 12:33:37.000000000 +0900
      @@ -418,9 +418,9 @@
      $row[] = $OUTPUT->user_picture($user, array(‘courseid’=>$course->id));
      }
      if (!$download) {
      – $row[] = ‘<a href="’.$CFG->wwwroot.’/user/view.php?id=’.$scouser->userid.’&amp;course=’.$course->id.’">’.$scouser->userid.'</a>’;
      + $row[] = ‘<a href="’.$CFG->wwwroot.’/user/view.php?id=’.$scouser->userid.’&amp;course=’.$course->id.’">’.$scouser->username.'</a>’;
      } else {
      – $row[] = $scouser->userid;
      + $row[] = $scouser->username;
      }
      if (empty($timetracks->start)) {
      $row[] = ‘-‘;

      — mod/scorm/report/basic/report.php.20151020 2015-10-20 11:04:48.000000000 +0900
      +++ mod/scorm/report/basic/report.php.20151016 2015-10-16 11:02:03.000000000 +0900
      @@ -121,7 +121,7 @@
      $columns[]= ‘picture’;
      $headers[]= ”;
      }
      – $columns[] = ‘userid’;
      + $columns[] = ‘username’;
      $headers[] = get_string(‘name’);

      $columns[]= ‘attempt’;
      @@ -383,9 +383,9 @@
      $row[] = $OUTPUT->user_picture($user, array(‘courseid’=>$course->id));
      }
      if (!$download) {
      – $row[] = ‘<a href="’.$CFG->wwwroot.’/user/view.php?id=’.$scouser->userid.’&amp;course=’.$course->id.’">’.$scouser->userid.'</a>’;
      + $row[] = ‘<a href="’.$CFG->wwwroot.’/user/view.php?id=’.$scouser->userid.’&amp;course=’.$course->id.’">’.$scouser->username.'</a>’;
      } else {
      – $row[] = $scouser->userid;
      + $row[] = $scouser->username;
      }
      if (empty($timetracks->start)) {
      $row[] = ‘-‘;

      — mod/scorm/report/objectives/report.php.20151020 2015-10-20 11:23:52.000000000 +0900
      +++ mod/scorm/report/objectives/report.php.20151016 2015-10-16 12:34:18.000000000 +0900
      @@ -422,9 +422,9 @@
      }
      if (!$download) {
      $row[] = ‘<a href="’.$CFG->wwwroot.’/user/view.php?id=’.$scouser->userid.
      – ‘&amp;course=’.$course->id.’">’.$scouser->userid.'</a>’;
      + ‘&amp;course=’.$course->id.’">’.$scouser->username.'</a>’;
      } else {
      – $row[] = $scouser->userid;
      + $row[] = $scouser->username;
      }
      if (empty($timetracks->start)) {
      $row[] = ‘-‘;
      [/code]

    2. 時刻処理に適したunixtime型で出力する
      [code]

      — course/lib.php 2015-10-20 11:46:28.000000000 +0900
      +++ course/lib.php.20151020 2015-10-20 11:26:45.000000000 +0900
      @@ -558,7 +558,6 @@
      $header = array();
      $header[] = get_string(‘course’);
      $header[] = get_string(‘time’);
      – $header[] = get_string(‘time’);
      $header[] = get_string(‘ip_address’);
      $header[] = get_string(‘fullnameuser’);
      $header[] = get_string(‘action’);
      @@ -622,7 +621,7 @@
      $firstField = format_string($courses[$log->course], true, array(‘context’ => $coursecontext));
      $fullname = $log->userid;
      $actionurl = $CFG->wwwroot. make_log_url($log->module,$log->url);
      – $row = array($firstField, userdate($log->time, $strftimedatetime), $log->time, $log->ip, $fullname, $log->module.’ ‘.$log->action.’ (‘.$actionurl.’)’, $log->info);
      + $row = array($firstField, userdate($log->time, $strftimedatetime), $log->ip, $fullname, $log->module.’ ‘.$log->action.’ (‘.$actionurl.’)’, $log->info);
      $csvexporter->add_data($row);
      }
      $csvexporter->download_file();

      — mod/quiz/report/attemptsreport_table.php 2015-10-20 11:20:12.000000000 +0900
      +++ mod/quiz/report/attemptsreport_table.php.20151020 2015-10-20 11:01:19.000000000 +0900
      @@ -163,7 +163,7 @@
      */
      public function col_timestart($attempt) {
      if ($attempt->attempt) {
      – return $attempt->timestart;
      + return userdate($attempt->timestart, $this->strtimeformat);
      } else {
      return ‘-‘;
      }
      @@ -176,7 +176,7 @@
      */
      public function col_timefinish($attempt) {
      if ($attempt->attempt && $attempt->timefinish) {
      – return $attempt->timefinish;
      + return userdate($attempt->timefinish, $this->strtimeformat);
      } else {
      return ‘-‘;
      }
      @@ -189,7 +189,7 @@
      */
      public function col_duration($attempt) {
      if ($attempt->timefinish) {
      – return $attempt->timefinish – $attempt->timestart;
      + return format_time($attempt->timefinish – $attempt->timestart);
      } else {
      return ‘-‘;
      }

      — mod/scorm/report/interactions/report.php 2015-10-20 11:23:34.000000000 +0900
      +++ mod/scorm/report/interactions/report.php.20151020 2015-10-20 11:21:52.000000000 +0900
      @@ -435,14 +435,14 @@
      $row[] = $scouser->attempt;
      }
      if ($download ==’ODS’ || $download ==’Excel’ ) {
      – $row[] = $timetracks->start;
      + $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig"));
      } else {
      – $row[] = $timetracks->start;
      + $row[] = userdate($timetracks->start);
      }
      if ($download ==’ODS’ || $download ==’Excel’ ) {
      – $row[] = $timetracks->finish;
      + $row[] = userdate($timetracks->finish, get_string(‘strftimedatetime’, ‘langconfig’));
      } else {
      – $row[] = $timetracks->finish;
      + $row[] = userdate($timetracks->finish);
      }
      $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt);
      }

      — mod/scorm/report/basic/report.php 2015-10-20 11:12:59.000000000 +0900
      +++ mod/scorm/report/basic/report.php.20151020 2015-10-20 11:04:48.000000000 +0900
      @@ -399,14 +399,14 @@
      $row[] = $scouser->attempt;
      }
      if ($download ==’ODS’ || $download ==’Excel’ ) {
      – $row[] = $timetracks->start;
      + $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig"));
      } else {
      – $row[] = $timetracks->start;
      + $row[] = userdate($timetracks->start);
      }
      if ($download ==’ODS’ || $download ==’Excel’ ) {
      – $row[] = $timetracks->finish;
      + $row[] = userdate($timetracks->finish, get_string(‘strftimedatetime’, ‘langconfig’));
      } else {
      – $row[] = $timetracks->finish;
      + $row[] = userdate($timetracks->finish);
      }
      $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt);
      }

      — mod/scorm/report/objectives/report.php 2015-10-20 11:24:46.000000000 +0900
      +++ mod/scorm/report/objectives/report.php.20151020 2015-10-20 11:23:52.000000000 +0900
      @@ -439,14 +439,14 @@
      $row[] = $scouser->attempt;
      }
      if ($download ==’ODS’ || $download ==’Excel’ ) {
      – $row[] = $timetracks->start;
      + $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig"));
      } else {
      – $row[] = $timetracks->start;
      + $row[] = userdate($timetracks->start);
      }
      if ($download ==’ODS’ || $download ==’Excel’ ) {
      – $row[] = $timetracks->finish;
      + $row[] = userdate($timetracks->finish, get_string(‘strftimedatetime’, ‘langconfig’));
      } else {
      – $row[] = $timetracks->finish;
      + $row[] = userdate($timetracks->finish);
      }
      $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt);
      }
      [/code]

  • 通研新棟を見学してきました

    「通研」とは、東北大学電気通信研究所のことで、光通信、八木宇田アンテナ、垂直磁気記憶、フラッシュメモリなど、数々の業績を積み重ねてきた研究所である。私などが紹介するまでもない。私の研究者としてのキャリアはここ通研からスタートしたため思い入れがある。そういう意味でも、通研が青葉山地区に移転することに一旦決まった時は寂しく思ったが、結局片平地区にとどまることになり、新棟が完成した。セミナーに登壇するため仙台を訪れたので素通りするわけには行かない。

    通研新棟入口より
    通研新棟入口より

    内部は開放的な空間が広がり、うらやましいの一言。

    RIECロゴは八木宇田アンテナをモチーフにしています
    RIECロゴは八木宇田アンテナをモチーフにしている

    菅沼研、木下研、FIRにおじゃましてきた。また、私を拾ってくださった鈴木陽一先生にご挨拶に伺ったところ、実験室を案内していただいた。しくみマニアとしては堪らない空間で凄いの一言。通研の皆様、本当にありがとうございました!

    無響室。ノイズを人間に聞こないレベルのさらに下に抑えた部屋で東大生研と並び国立大学随一の設備とのこと。
    無響室。ノイズを人間に聞こないレベルのさらに下に抑えた部屋で東大生研と並び国立大学随一の設備とのこと(鈴木陽一先生談)。床はさらに2mていど下にある。
    シールド室。シートはリニアモーター駆動で移動でき、不要なノイズが発生しない。
    シールド室。シートはリニアモーター駆動で移動でき、不要なノイズが発生しない。
  • Moodle + BigBluebutton で遠隔会議

    研究室メンバーで遠隔会議をしたいとき、Skype IDとかを教え合えば済むのかもしれないがちょっと違うような気がする。そこで、Moodleと親和性の高いオープンソースのWeb会議システムBigBluebuttonを試してみた。BigBluebuttonはOSをUbuntuに限定している。BigBluebuttonは様々なソフトウェア(Red5、nginx、ffmpegなどなど)の集合で、全てのディストリに対応するのは難しいのだろう。

    BigBluebuttonそのもののインストールは三重大学の三島先生の記事を参考にさせていただいた。三島先生ありがとうございます。Requirementには「物理サーバ」とあるが、今回は仮想環境にインストールした。既存のMoodle側についてはプラグインを解凍し、認証キーの設定をするだけである。

    この後はMoodleの「アクティビティ」に現れるBigBluebuttonを選択し追加すれば遠隔会議へのリンクが作成され、拍子抜けするくらい簡単。つまり、会議に参加する際にMoodleにログインしていれば追加の認証はなく、Moodleのユーザ名が自動で引き継がれる。つまり、MoodleのアカウントがあればBigBluebuttonで遠隔会議が可能となる。

    早速、テストを兼ねて本日の研究室ゼミに東北大学からの遠隔参加を試してみたが、接続そのものとWebCamの映像の確認はできたものの、PCのデバイスの関係か、マイクが使えずNGとなってしまった。次回はMacで試してみよう。

    2015/10/09追記:KUINS側で必要なポートが学外に開放されていないことが分かったので開放を申請中。
    2015/10/23追記:開放が完了し、WebRTCも問題なく使えるようになった。チェックするにはbbbサーバ以下の check/ にアクセスすれば良い。
    2015/12/01追記:問題なく利用できており、遠隔ミーティング、ゼミの遠隔参加など時間の有効活用ができるようになった。

  • 仙台「有線・無線LANによるシングルサインオンと学認連携について」セミナーで講演しました

    7月29日の京都会場に続き仙台でも登壇させていただいた。仙台は私のキャリアのスタートとなった思い出の地である。通研で拾ってもらっていなければ今の私は無いと断言できる。会場では思わぬ再会があり、懐かしい記憶が思い返された。

    AER21階が会場でした
    AER21階が会場でした

    講演内容は京都会場とアウトラインは同じものの、内容を取捨選択したので時間内にSINET群馬ノードを移設した話(!)までできた。ITに限らず、このような「どうなるか分からない改革」は結局ユーザとの信頼関係が全て(つまり「何を言ったか」より「誰が言ったか」になる)。今はそのような関係を築く立場からは外れてしまったものの、これらの経験は私の仕事を進める上でのいちばんのモチベーションとなっている。

    お招きいただきありがとうございました。NetSpring、ALE関係各位に御礼申し上げます。

  • 「学認クラウドと連携ソリューション事例紹介セミナー」で講演しました

    「Microsoftとの決別」とスライドには表示されていますw
    「Microsoftとの決別」とスライドには表示されていますw

    ファルコンSCの山下さんから登壇依頼があり、「学認クラウドと連携ソリューション事例紹介セミナー」で「Shibboleth認証連携でOffice365 Educationを実運用するまでの長い道のり」と題して講演を行った。私自身3月末で運用から離れているため、これがほんとうに最後になると思っている。このところ登壇が続いているのと、講演時間が50分だったので余裕を持って喋れると思っていたのだが、それがあだになり尻切れトンボになってしまった(すみません)。

    今回の聴衆は認証連携の人達のはずなので、どのような(ややこしい)仕組みでOffice365のShibboleth連携を行っているかについて、自分なりに整理して話すように努めた。それなりに歴史があるMicrosoftのオンラインサービスの品質について考えていただくきっかけになれば幸いである。

    セミナー全体は、学認クラウドのご担当者が苦労されている話とか、福岡大学の生体認証の研究紹介など、ひじょうに興味のある話ばかりで、その後の懇親会も盛り上がった。主催者のファルコンSC、サイボウズ、日立電線ネットワーク各社様、またセッションに参加された皆様、どうもありがとうございました。

  • Amazon Web Services 実践入門/Architecting on AWSに参加

    トレーニングで使用する演習環境のLMSのようなもの。慣れが必要であった。
    トレーニングで使用する演習環境のLMSのようなもの。慣れが必要であった。

    enPit関連のMLで知り、無理をして参加しました。実践入門とArchitecting…で5日間必要なのですが、3日間のみの参加です。それぞれは本当なら一日あたり$600ということなのですが、今回の企画は無料でした。「AWSはすごい」というのはよく聞きますし、通常使っている「なんちゃってクラウド」に嫌気がしており、AWSがなんぼのものか興味があったのです。

    • EC2/EBS
    • S3/Glacier
    • ELB
    • VPC

    最初の2日で、EC2のインスタンスを立ち上げ、WordPressのスタティックコンテンツはS3に格納、その前段にCloudFrontによるキャッシュを実装しました。また、EC2のAuto ScalingやELBの機能について学びました。3日目はより詳しく、IAM、EC2、S3について、またオンプレをどのようにAWSに移行するかのディスカッションを行いました。

    感想。今更ですがAWS凄いです。これは大学でプライベートクラウドとか構築してる場合ではありません。情報系センターの仕事がなくなります。一方、実際に学んでみてAWSが魔法のシステムではないということも分かりました。早速NASのバックアップにS3とGlacierを使おうと思います。

    ハードルがあるとしたら、月額○○とか年額○○という料金体系に飼い慣らされてきた日本での従量課金でしょうか。今後どのような展開が待っているか楽しみです。

  • 「IT+教育最前線 2015セミナー大阪」で講演しました

    Office365 Education の本質:ソフトウェア、システム運用、サポート体制の観点から
    Office365 Education の本質:ソフトウェア、システム運用、サポート体制の観点から

    3年前にも登壇したセミナーに再度呼んでいただきました。これまでの3年半のマイクロソフトのオンラインサービスの運用を総括しました。つまり、CLE16の続編ということになり、スラドで「論文の体をなしていない」とか「雑文だ」とか批判されたことを反省し(いやそもそもCLEは研究会なんで論文ではなく、論文と言っているのはスラドなのですが)、もう少し体系的、つまりオンラインサービスは次の三要素からなっているという考えからまとめようとしたものです(講演資料)。

    • ソフトウェア
    • システム運用
    • サポート体制

    いずれの観点からも「否」と言いたいのではなく、ソフトウェアにはバグがつきものです。システム運用のミスは信頼を失う原因になります。しかし、サポート対応でこれらのマイナス面はいかようにでもなります(生身の人間ですから)。でも、サポートとのやり取りのメールが、意味不明で冗長な日本語の繰り返しだったらどうでしょう。最悪ですよね。たとえばこんなのです。

    再発防止につきましては、短期的な対策の実施および、長期的な取り組みをそれぞれ実施している状況となります。具体的な内容や時期についてはお伝えする事ができずに申し訳ございませんが、引き続き改善に努めさせていただく所存でございます。

    これ、何も言っていないのと同じですよね…。ユーザとのインタラクションがすべての印象を決めてしまうということを認識していないのでしょうか?