2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

GASウェブアプリでプランニングポーカーを作ってみた

Last updated at Posted at 2021-09-23

GASウェブアプリでプランニングポーカーを作ってみた

image.png

利用してみたい方は、こちら

背景

チームでプランニングポーカーを実施していた時に、13〜21って範囲が少し広すぎるよとか気づいたら接続切れてて部屋作り直しになったなど、大した問題ではないが、少し使い勝手の悪さを感じていたので自作してみました。

利用技術

  • Google Apps Script
  • Vue.js
  • Bulma

仕組み

image.png

  • Clientで稼働するのは、Vue.js+Bulmaで構築される画面
  • GoogleAppsScriptでは、Roomのデータ管理を実施

機能紹介

  • 選択項目を誰でも好きなように変更可能

    • プリセットされている選択項目は4つ
    • 値は変更可能であり、制限も設けていないので自由な文字に変更可能
    • + -ボタンで自由に追加削除可能
  • 作成した部屋にアクセスするID付きURLをクリップボードコピー

    image.png

  • カード表示の各種機能

    image.png

    • アイコンにより、選択中/済みが判別可能
    • 右上のxボタンで退場する、させることが可能
    • 全員の選択が完了すると自動オープン
  • 選択結果の平均、最大、最小表示

    image.png

  • Ghostモード参加機能

    image.png

    • ポーカーに参加しないが、見学する場合にカードを選択が制限されている状態で参加することが可能

実装

  • 動作させる場合は、以下の手順で実施してください。
    1. GoogleAppsScriptを新規作成して、GitHubのプログラムを登録する。
    2. .html は、HTMLで登録、 .gs は、スクリプトで登録してください。
    3. デプロイ - 新しいデプロイでウェブアプリとしてデプロイする。
      設定画像


    4. トリガー - トリガーを追加 - deletePropertyを1時間おきで登録する。
      設定画像


    5. 発行されたURLにアクセスする。

POINT説明

データはGASのPropertiesServiceを利用

main.gs
const saveRoomData = (id, data) => PropertiesService.getScriptProperties().setProperty(id, JSON.stringify({
  ...data, 
  lastUpdated: (new Date()).toISOString()
}))

const getRoomData = (id) => {
  const property = PropertiesService.getScriptProperties().getProperty(id)
  return property ? JSON.parse(property) : false
}

よくある、GASといえばSpreadSheetでも良いのですが、比較的短時間の利用であることと、データを保管し続けない(roomの利用が終了すると不要データになる)ことから、PropertiesServiceを利用しています。
格納できるデータ上限もありますが、一時保存先なので十分であると判断しました。

また、定期的に不要になったデータを削除するトリガーを設定してクリーニングしています。

main.gs
const deleteProperty = () => {
  const properties = PropertiesService.getScriptProperties().getProperties()
  const checkDate = new Date()
  checkDate.setHours(checkDate.getHours() - 2)
  Object.keys(properties)
    .filter(key => JSON.parse(properties[key]).lastUpdated < checkDate.toISOString())
    .forEach(key => PropertiesService.getScriptProperties().deleteProperty(key))
}

データ同期は、2秒おきのポーリング

index.html
  polling: async function() {
    if (this.isPolling) return
    this.isPolling = true
    while (this.isPolling) {
      await new Promise(resolve => setTimeout(resolve, 2000))
      google.script.run.withSuccessHandler((response) => {
        const updateRoomData = response.roomData ? JSON.parse(response.roomData) : null
        if (!updateRoomData || !updateRoomData.users[this.userId]) {
          window.open(this.url, '_top')
          return
        }
        this.roomData = updateRoomData
      }).withFailureHandler((e) => {
        console.log(e)
      }).polling(this.roomId)
    }
  },

同時接続部屋を作るのが得意なWebSocketを利用する方法も考えたのですが、サーバーが必要になるので
今回は、ポーリングで実現しました。

感想

ここをベースに、チームにあった選択項目や、カード表示にカスタマイズしていくことで、楽しいプランニングポーカーが実施できるのではないかと感じました。

当初はGASで利用していたのですが、実際に運営してみると好評だったので
現在は、GASからFirebaseにリホストして、公開しています。
お試し利用していただけると嬉しいです。

データ同期もFirestoreになっているのでサクサク稼働するようにも改善されています、

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?