HIDARI日記(右)

そのときどき興味ある技術を中心にだらだら書いてます。内容は個人の見解であり、所属する企業を代表するものではありません。

はじめてVirtual DOMを触ったよ

Room metro #29 に参加して VirtualDOM をほんの少し教わったので忘れないうちに書いておきます(とかいいつつすでに怪しいけども)。

ほとんど当日のメモそのままなので内容的にアレなところあるかも(言い訳

VirtualDOMってなにか

HTMLのDOMと全く同じものをJSで作ったもの。

本来ブラウザのものであるDOMを、JSのオブジェクトとして仮想的に構築したデータ構造。

今まではブラウザが持つDOMを直接触ってた。 するとDOM変更のタイミングで毎回ブラウザのレンダリングが走る。これはとても重い処理。 この重さを軽減するために、VirtualDOMを使ってJSで変更を行ったあと、まとめてDOMに反映する。

VirtualDOMからのDOMの更新では、更新前のVirtualDOMとの差分だけが実際のDOMに反映される。これによって無駄な更新が入らず速度面で有利になる。VirtualDOMがイケてるところ。と言われている。 ここを抑えておかないとそこらの記事はナンノコッチャになる。

話題の?Reactとは

Virtual DOMを使ったプロダクト。まだよくわからん。

今回の続きとして勉強会を計画中とか風のうわさで本人から聞いたので楽しみにしてます。

ハンズオン

Matt-Esch/virtual-dom

を使って簡単なTODOアプリを作成。 上記のライブラリは本当に生のVirtualDOMを扱うもので、通常はこれをラップしていい感じにVirtualDOMを操作してくれるライブラリを使うとのこと。

ざっくりと手順の紹介

まずは virtual-dom/dist at master · Matt-Esch/virtual-dom から virtual-dom.js をローカルに保存。

次にVisualStudioから新しくASP.NET Applicationプロジェクトを作成。

f:id:hidari-yori:20150202225007j:plain

この時、空のテンプレートを選択して余計なフォルダーや参照は追加しないようにする。

f:id:hidari-yori:20150202225031j:plain

ASP.NET Applicationプロジェクトが作成できたら、そこにHTMLファイル追加。

f:id:hidari-yori:20150202225057j:plain

さらに、先ほどダウンロードした virtual-dom.js を追加。

f:id:hidari-yori:20150202225123j:plain

ここまでが準備。この状態まで持ってこれたら、あとはひたすらコードを書いていくだけ。

そしてできたものがこちら。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="virtual-dom.js"></script>
<title>Hoge</title>
</head>
<body>
<div>
<input type="text" name="todo"/>
<button type="button" name="add">add</button>
</div>
<div class="list"></div>
<script>
   var todos = [],
   textbox = document.querySelector("[name=todo]");

   document.querySelector("[name=add]").addEventListener("click", function () {
       var todoText = textbox.value;
       todos.push(todoText);

       var newTodoVDom = createVDom(todos);
       var patch = virtualDom.diff(todoVDom, newTodoVDom);

       todoNode = virtualDom.patch(todoNode, patch);
       todoVDom = newTodoVDom;

   }, false);

   function applyTodosVDom(todos)
   {
       var newTodoVDom = createVDom(todos),
       patches = virtualDom.diff(todoVDom, newTodoVDom);

       todoNode = virtualDom.patch(todoNode, patches);
       todoVDom = newTodoVDom;
   }

   function createVDom(todolist) {
       var textVDoms = todolist.map(function(todo) {
           return virtualDom.h("div", {}, [
           virtualDom.h("button", {
               onclick: function() {
                   todos.splice(indexedDB, 1);
                   applyTodosVDom(todos);
               }
           }, "complete!"),
           virtualDom.h("span", {}, todo)
           ]);
       });

       return virtualDom.h("div", {}, textVDoms);
   }

   var todoVDom = createVDom(todos);
   var todoNode = virtualDom.create(todoVDom);
   document.querySelector(".list").appendChild(todoNode);
</script>
</body>
</html>

おわりに

以上がはじめてのVirtualDOM体験でした。

めとべやのみなさんありがとうございました。

「イシューからはじめよ」を読んだ

イシューからはじめよ―知的生産の「シンプルな本質」

イシューからはじめよ―知的生産の「シンプルな本質」

せっかく読んだので、気になった、あるいは気に入ったところのメモ。

明確化する

「これは何に答えを出すためのものなのか」というイシューを明確にしてから問題に取り組まなければ後で必ず混乱が発生し、目的意識がブレて多くのムダが発生する。

それから

「こんな感じのことを決めないとね」といった「テーマの整理」程度で止めてしまう人が多いが、これでは まったく不足している(中略)「やってみなければわからないよね」といったことは決して言わない。ここで踏ん張り切れるかどうかが、あとから大きく影響してくる

さらに発展して

「できる限り先んじて考えること、知的生産における段取りを考えること」を英語で「Think ahead of the problem」と言う。

怒られてる気がした。これやっちゃって失敗してるわーって。

「今はまだわからない」って思考停止は実行するのが簡単すぎる。諦める前に一歩立ち止まりたい。

諦めるな、僕。

方向を定める

よいイシューの表現は、「~はなぜか?」といういわゆる「WHY」ではなく、「WHERE」「WHAT」「HOW」の形をとることが多い。

問題を整理しようとするとき、僕達はよく、「なぜ」という言葉を使うけど、「なぜ」という言葉は問題の本質をぼやけさせてしまうように思う。

「答え」が存在する

どれほどカギとなる問いであっても、「答えを出せないもの」はよいイシューとは言えないのだ。「答えを出せる範囲でもっともインパクトのある問い」こそが意味のあるイシューとなる。

筆者は本書の冒頭で、 「悩む」=「答えが出ない」「考える」=「答えが出る」 という考え方を示している。それだけでなく「答えが出るものの中でも最も影響が大きいものを扱うようにしろ」と言っている。

すべての「答えが出るもの」を扱うには人間は小さすぎる。

やりすぎ

情報収集にかけた努力・手間とその結果得られる情報量にはある程度のところまでは正の相関があるが、そこを過ぎるととたんに新しい取り込みのスピードが鈍ってくる。

また

ある情報量までは急速に知恵が湧く。だが、ある量を超すと急速に生み出される知恵が減り、もっとも大切な「自分ならではの視点」がゼロに近づいていくのだ。

取り入れる情報量には注意しないと、気を抜くと自分で考えることをやめてしまったり、自分でも気づかないうちに集めた情報によって考えの幅が狭められたりしてしまう。

集めた情報に逆に洗脳されちゃうような感じは確かにある。そして

数字をこねくり回さず、手早くまとめることが大切だ。1回ごとの完成度よりも取り組む回数(回転数)を大切にする。また、90%以上の完成度を目指せば、通常は途方もなく時間がかかる。そのレベルはビジネスではもちろん、研究論文でも要求されることはまず無い。そういう視点で「受け手にとっての十分なレベル」を自分のなかで理解し、「やり過ぎない」ように意識することが大切だ。

ただでさえ、僕は時間をかけ過ぎると飽きちゃうので、モチベーションをマネジメントするためにも「一つ一つをやり過ぎ、短い時間で複数回」というのは気をつけないと…

努力というか

既存の手法についてひと通りなじむには、どのような分野であっても相当な年数がかかる。

さらに

実際のところ、どのような分野であっても、多くのプロを目指す修行のかなりの部分はこれら既存の手法、技の習得に費やされる。

周りの人たちを見ているとわかってくるのだけど、一つの分野で素晴らしいパフォーマンスとクオリティで仕事をしている人たちは、みなさん驚くほど引き出しを持っておられる。 そこに追い付きたいし、追い越したい。たぶんそこには近道なんか無いんだろうなーってよく思う。

プロとしての意識

「コンプリート・スタッフ・ワーク(Complete Staff Work)」これは「自分がスタッフとして受けた仕事を完遂せよ。いかなるときにも」という意味だ。この「コンプリートワーク」という言葉はプロフェッショナルとして仕事をする際には、常に激しく自分にのしかかってくる。

完遂の定義にもよるけど、というか完遂の定義を事前にしておかないといけないな。

まあそれとは別に、たとえクソのようなプロジェクトでも何とかして着陸させないといけないし、そういう意味ではやっぱり働く上で一番必要な心構えだと思う。

イキルサイノウ

「人から褒められること」ではなく、「生み出した結果」そのものが自分を支え、励ましてくれる。

自分で生み出したという事実だけが生きる勇気をくれるのではないか。そう考えるとちょっと光が見える気がする。

おわりに

読んでよかった一冊です。

気に入ったフレーズだけをピックアップしましたが、本文はもっと具体的な例、論文を書く際やプレゼンテーションの資料を作る際に参考になる考え方が示されていたので、初めて論文を書くことになる大学生なんかは読んでおいて損はないんじゃないかと思います。

はじめてAppVeyorで.NETベースのプログラムのCI環境を構築した

手元でJenkinsを動かしてCI環境を構築するのもいいのだけれど、一度くらいCIサービスを使ったCIを実行したいと思い立ったので実行してみました。

現状で.NET言語用のCIサービスといえば AppVeyor なので、これを使ってCI環境を構築した話です。

AppVeyorはOSSのCIなら無料で使えるため、GitHubなどを使って開発している場合は非常にありがたいです。

ちゃきちゃきやっていく

ごちゃごちゃっとサインアップしてしまいましょう。GitHubアカウントを使ってサインアップしておくと便利。

画面上部の「+NEW PROJECT」を選ぶと各種ホスティングサービスのからリポジトリを選択できるようになるのでビルドしたいものを選びます。

f:id:hidari-yori:20150118223911j:plain

ところでこのサービス選択の中にVisual Studio Onlineが入ってて、おおなるほどなってなりました(そらそうや。

f:id:hidari-yori:20150118224039j:plain

プロジェクトを追加したら、画面上部の「SETTINGS」からお好みな設定を作ります。

ビルド中のビルドの前後、テストの前後など色々なタイミングで好きな処理を挿し込めるようにPowershellコマンドプロンプトスクリプトを設定できますのでいい感じに利用しましょう。

一点だけ注意点。

Nugetパッケージの自動復元はデフォルトでは行われません。

なので About NuGet package restore - Appveyor を参考に設定を行う必要があります。

手っ取り早いのは [SETTINGS] > [Build] > [Before build script] に以下のスクリプトを追加する方法でしょうか。

nuget restore

これを忘れるとちょっとどきどきすることになります。

f:id:hidari-yori:20150118225130j:plain

バッジつけたい

[SETTINGS] > [Badges] から各種「Project status badge」が選べます。

リポジトリのREADME.mdに載せるならマークダウンなやつをコピペするのがいいかと思います。

おわりに

びっくりするぐらい簡単なので積極的に使っていきたい。特にVisual Studio Olineで…

PowershellからMSBuildを動かす

まあ別段MSBuildに限った話ではなくて、外部プロセスを起動したいときは同じ考え方ができますが。

やりたいこと

MSBuild.exe MyApp.sln /t:Rebuild /p:Configuration=Release

みたいなのをラップして

Build-VsProject -Path .\MyApp.sln -Options "/t:Rebuild /p:Configuration=Release"

で実行可能にすることを目指します。

どうやるか

パッと浮かぶのは Start-Process か Call Operator & を使う方法。

ただ Start-Process にしろ & にしろ、コンソールからちょろっと使うにはいいけど、 スクリプトで使うのは終了コードの取り方が面倒だったりして辛いかも。

なので System.Diagnostics.Process と, プロセス実行時の設定を行うための System.Diagnostics.ProcessStartInfo を自前で作る方法で行くことにします。

.NETのクラスを使うほうが安心感ありますし(謎。

書いていきましょう

System.Diagnostics.Process はこんな感じで書ける。

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = MSBuild.exe
$pinfo.Arguments = "Path\to\MyApp.sln /t:Rebuild /p:Configuration=Release"
$pinfo.RedirectStandardOutput = $true
$pinfo.RedirectStandardError = $true
$pinfo.UseShellExecute = $false

$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $pinfo
$proc.Start() | Out-Null

$proc.RedirectStandardOutputプロパティと$proc.RedirectStanderdErrorプロパティの設定はお好みで。 このプロパティをtrueにしておくと、起動したプロセスの標準出力を取得できるようになります。

この時の注意点として、RedirectStandardOutputプロパティやRedirectStanderdErrorプロパティをTrueにするときは必ずUseShellExecuteプロパティをFalseに設定する必要があります。しないと例外が飛んできます(http://msdn.microsoft.com/ja-jp/library/system.diagnostics.processstartinfo.redirectstandardoutput(v=vs.110).aspx)。

$stdOut = $proc.StandardOutput.ReadToEnd()
$errOut = $proc.StandardError.ReadToEnd()

という感じに使うことができます。

終了コード欲しいよね

実行したプロセスの終了コードは$proc.ExitCodeプロパティで取得可能なので $proc.WaitForExit()$proc.HasExitプロパティなんかと合わせて使います。

$proc.StartInfo = $pinfo
$proc.Start() | Out-Null
$proc.WaitForExit()

if($proc.ExitCode -eq 0){
    Write-Host "Build has Succeedes!!"
}
else{
    Write-Host "Build has failed..."
}

さて、これで上手くいくと思うじゃろ?

WaitForExit()の罠

そんなことはなく。

$proc.WaitForExit()にはハマリポイントがあります。

$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = MSBuild.exe
$pinfo.Arguments = "Path\to\MyApp.sln /t:Rebuild /p:Configuration=Release"
$pinfo.RedirectStandardOutput = $true
$pinfo.RedirectStandardError = $true
$pinfo.UseShellExecute = $false

$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $pinfo
$proc.Start() | Out-Null
$proc.WaitForExit()

$stdOut = $proc.StandardOutput.ReadToEnd()
$errOut = $proc.StandardError.ReadToEnd()

とか素直に書いてしまうとプロセスが終了せずに固まってしまいます。 原因はMSBuildからの出力によってStandardOutputのバッファいっぱいになり、そこで処理が止まってしまうため。

これをいい感じに吸い出してやる必要があります。そのためにOutputDataReceivedイベントと$proc.BeginOutputReadLine() を使って非同期に出力を読み取ります。

手順は以下の通り。

  1. BSBuildの出力を保存する追記可能なストアとしてStringBuilderを用意
  2. OutputDataReceivedイベントで行いたい処理をスクリプトブロックに記述
  3. OutputDataReceivedのイベントハンドラを登録
  4. プロセスを実行
  5. $proc.BeginOutputReadLine()で読み取り開始
  6. プロセス終了後に読み取った出力を適当に書き出す

この流れで書いたのが以下のコードです。

$proc = New-Object System.Diagnostics.Process
$proc.StartInfo = $pinfo

# 出力の格納先としてStringBuilderを用意
$stdOutBuilder = New-Object -TypeName System.Text.StringBuilder
$stdErrBuilder = New-Object -TypeName System.Text.StringBuilder

# イベントを利用して出力を書き出す
# まずスクリプトブロックにイベントで行いたい処理を記述
# ここではStringBuilderに出力を格納する
$action = {
    if(![string]::IsNullOrEmpty($EventArgs.Data)){
        $Event.MessageData.AppendLine($EventArgs.Data)
    }
}

# イベントハンドラを登録
$stdOutEvent = Register-ObjectEvent -InputObject $proc -Action $action -EventName "OutputDataReceived" -MessageData $stdOutBuilder
$stdErrEvent = Register-ObjectEvent -InputObject $proc -Action $action -EventName "ErrorDataReceived" -MessageData $stdErrBuilder

# プロセスを開始
[void]$proc.Start()

# 非同期で出力の読み取りを開始
$proc.BeginOutputReadLine()
$proc.BeginErrorReadLine()
$proc.WaitForExit()

# 最後に読み取った出力を書き出す
$stdOutBuilder.ToString() | Out-File ".\BuildLog.txt"
$stdErrBuilder.ToString() | Out-File ".\ErrorLog.txt"

思った以上に面倒なコードになりました。

コード全体

というわけで最終的に出来上がった?コードはこんな感じでした。ちょっと高度な関数風にしてみました。

function Build-VsProject
{
    [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="Low")]
    param
    (
        [Parameter(
            Mandatory=$true,
            Position=0
        )]
        [alias("SolutionPath")]
        [string]
        $Path,

        [string]
        $Options
    )

    begin
    {
        $msb="C:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe"
    }

    process
    {
        if(-not(Test-Path -Path $msb)){throw "MSBuildNotFoundException"}

        Write-Host "Start Build $Path"

        $pinfo = New-Object System.Diagnostics.ProcessStartInfo
        $pinfo.FileName = $msb
        $pinfo.Arguments = "$Path /t:Rebuild /p:Configuration=Release"
        $pinfo.RedirectStandardOutput=$true
        $pinfo.RedirectStandardError=$true
        $pinfo.UseShellExecute=$false
        $pinfo.CreateNoWindow=$true

        $proc = New-Object System.Diagnostics.Process
        $proc.StartInfo = $pinfo

        $stdOutBuilder = New-Object -TypeName System.Text.StringBuilder
        $stdErrBuilder = New-Object -TypeName System.Text.StringBuilder

        $action = {
            if(![string]::IsNullOrEmpty($EventArgs.Data)){
                $Event.MessageData.AppendLine($EventArgs.Data)
            }
        }

        $stdOutEvent = Register-ObjectEvent -InputObject $proc -Action $action -EventName "OutputDataReceived" -MessageData $stdOutBuilder
        $stdErrEvent = Register-ObjectEvent -InputObject $proc -Action $action -EventName "ErrorDataReceived" -MessageData $stdErrBuilder
        [void]$proc.Start()
        $proc.BeginOutputReadLine()
        $proc.BeginErrorReadLine()
        $proc.WaitForExit()

        Unregister-Event -SourceIdentifier $stdOutEvent.Name
        Unregister-Event -SourceIdentifier $stdErrEvent.Name

        $stdOutBuilder.ToString() | Out-File ".\BuildLog.txt"
        $stdErrBuilder.ToString() | Out-File ".\ErrorLog.txt"

        if($proc.ExitCode -eq 0){
            Write-Host "Build has Succeedes!!"
        }
        else{
            Write-Host "Build has failed..."
        }

        return $proc.ExitCode
    }

    end
    {
    }
}

おわりに

みたいなことを書こうとしてるところでぎたぱそ先生がPowerShell で System.Diagnostic.Process にて BeginOutputReadLine() を使う - tech.guitarrapc.cómを投稿しておられるのに気づいて会社でぶったまげたことをご報告致します。

さすがMVP。わかりやすい...脱帽するしかないけど、これからも強く儚く生きていこうと思います。よろしくお願いします。

またこの記事を書くにあたり発破をかけて下さった@Posauneさんと@irofさんに感謝。

WindowsでのHubotのインストール手順 Hubot@2.9.3

node.jsのインストール

node.jsからmsiを落としてきてインストールする。他の方法は知らない。nodebrewとかWindowsで使えんのかな?誰か教えて><。

npmフォルダの作成

node.jsのインストーラの問題(node.js - nodejs/windows Error: ENOENT, stat 'C:\Users\RT\AppData\Roaming\npm' - Stack Overflow)でnpmが動かなくて焦った。自分でC:\Users\<YOUR_NAME>\AppData\Roamingの下にnpmってフォルダ作らなきゃいけない。

CoffeeScriptのインストール

npm install -g coffee-script しましょう。

yeoman と generator-hubotのインストール

ググったらいっぱい出てくる npm hubot でのインストールはScriptsフォルダがなかったりしてhubot hellohubot pingも動かない。代わりにyeoman使う。

npm install -g yo generator-hubot

自分のHubotを生成する

適当にHubot用のフォルダを作ってyo。

mkdir hubot-test
cd hubot-test
yo hubot

コマンド実行中にHubotのアスキーアートが表示されておしゃれ。

external-scripts.jsonの修正

ひとまずコンソールで動かすだけなので hubot-test\external-scripts.jsonから hubot-heroku-keepalivehubot-redis-brain を削除する。これをしとかないとhubot実行時にエラーが出るので。必要になりそうなときは適当にバックアップする。

Hubotの実行

cd hubot-test
.\bin\hubot

動作確認

Hubot> hubot ping
Hubot> PONG

Scriptsに自分のスクリプトを追加してみる

自分の作ったスクリプトhubot-test\scripts に置くとHubotに認識されるので試してみた。

GoodNight.coffee

module.exports = (robot) ->
    robot.respond /GOOD NIGHT$/i, (msg) ->
        msg.send "おやすみうみう"

おわりに

第1回 Hubot×ChatOps勉強会 - connpassに参加してきた勢いでやった。反省してない。

あと、今回書いた情報もそのうち腐ってくると思うのでご注意を。

土壁を壊すときに忘れてはいけない5つのもの

この前の日曜日のことです

ヌーラボさんの京都事務所の移転のため、移転先の京都の民家を自分たちで改装するという計画?に誘っていただいたので、この前の日曜日、ほいほい遊びに行ってきました。

詳細はこちら。

「ITの開発会社がオフィスをDIY?! vol.1〜株式会社ヌーラボ」│ 京都移住計画

この日は主に壁壊す日。改装で取り払う土壁を、せっかくなのでみんなでわいわい壊してしまおうという企画でした。

参加してみて感じたことを今後のために残しておこうと思います。

土壁を壊すときに忘れてはいけない5つのもの

1. 防塵マスク

マストアイテム。

僕は持っていくのを忘れてしまい、ご好意で貸していただくことが出来ました。

しかし本来であれば自分で用意していくべきもの。自分の顔の形にあったものを用意していくのが吉。

2. ゴーグル

マストアイテム、その2。

恥ずかしながらゴーグルも持参せずお借りしてしまいましたが、これも事前にきちんと用意すべき。フィット感が大事。

マスクとゴーグルがくっついたタイプでも可。

3. タオル

かなりの重労働なので大量の汗をかきます。予備も合わせて3枚くらいあると多い日も安心。

4. 水

特に夏場は十分な水分補給が命綱。

5. お風呂の準備

壁を壊したあとは身体の汚れが気になります。作業後に銭湯に行きたくなることうけあい。

なんと新しいヌーラボ京都事務所の近所には銭湯があります。汚れた身体をさっぱりさせたいものです。

おわりに

いかがでしたでしょうか。 ここで紹介したアイテムを用意すればあなたも明日から立派な壁壊er(てきとう。

防塵マスク イスラエル軍仕様

防塵マスク イスラエル軍仕様

艦これ2014夏イベント反省会

お疲れ様でした

2014年8月29日のアップデートをもって、今年の艦これ夏イベント「期間限定海域【AL / MI作戦】」が終了しました。

今回はかなりガチで挑んだけど、春イベントに続き全ステージクリアはなりませんでした。

編成や戦績はこちらのgistで公開しています。

艦これ艦隊日誌_2014夏イベント.md

最終ステージの壁は厚かった…。 届かなくて悔しかったので一人、反省会を行いたいと思います。

反省点

  • 試行回数の不足
    • 前半に時間かけすぎ
      • 情報収集に時間を取り過ぎてスタートが遅れた
      • 予備艦に不安があったため日和った
    • 3重キラに拘り過ぎて、試行回数が少なくなってた
      • キラ無しで試行回数増やす
      • 疲労回復の時間を使って可能なだけキラ付けする
      • 運の要素が強いから、それに抗うためには試行回数を増やす以外にない。
    • イベント中は出撃できないようなスキマ時間にキラ付けしておいて、まとめて回数出撃するほうが試行回数増やせる気がする
  • 燃料不足
    • 確か最初は6万弱あった最終的には燃料が1万切ったし10万以上は必要そう
    • 燃料に限らず10万以上はほしいところ
  • 駆逐艦、軽空母の戦力不足
    • 事前に育ててた艦娘たちが戦艦、正規空母などに偏ってた
    • 支援艦隊が十分ではなかった疑惑
  • 自戦力が把握できてない部分があった
    • 戦艦とか余ってた
    • 長門使ってなかった…

成果

ちなみに全く成果がなかったわけではないです。

  • 大鯨
  • 清霜
  • あきつ丸
  • 三隈
  • 春雨
  • 雲龍
  • 時津風
  • 大淀
  • 長波

といった感じ。レア艦娘のドロップはさすがイベント海域といったところ。

おわりに

戦力が把握しきれていなかった点と偏っていた点については日々の演習を上手く利用しながら整えていくつもりです。

ですが結局のところ資材と試行回数が足りなかったのが一番大きな問題のように思われます。

次回のイベントではこれを改善することを目標に準備していこうと思います。