GAS で Google カレンダーの1日の空き時間を取得する

最近予定が詰まっているのでスキマ時間がどれくらいあるのか取得したくなった。ので GAS で書いた。

function myFunction() {
  const calendar = CalendarApp.getCalendarById('hogehogei@example.com');

  const date = new Date();
  
  const freeTime = getFreeTimeMinutes(calendar, new Date());

  // あとは気分に応じて Slack に投げたりする
}

function getFreeTimeMinutes(calendar, date){
  const events = calendar.getEventsForDay(date);
  
  // 終了時間の昇順にした後に開始時間の昇順にする
  const sortedEvents = events.sort(function(a, b) {
    return a.getEndTime() - b.getEndTime();
  }).sort(function(a, b) {
    return a.getStartTime() - b.getStartTime();
  });
 
 // 時間がかぶっている予定をひとまとめに `block` とする
  const blocks = [];
  var block = {
    start: sortedEvents[0].getStartTime(),
    end: sortedEvents[0].getEndTime()
  };
  
  sortedEvents.forEach(function(event) {
    const start = event.getStartTime();
    const end = event.getEndTime();
    
    if(block.end < start){
      blocks.push({
        start: block.start,
        end: block.end
      });
      block.start = start;
      block.end = end;
    }
        
    if(block.end < end){
      block.end = end;
    }
  });
  
  blocks.push({
    start: block.start,
    end: block.end
  });
  
  // 9:30 - 18:00 を定時とする
  const bizStart = new Date(date.getYear(), date.getMonth(), date.getDate(), 9, 30, 0);
  const bizEnd = new Date(date.getYear(), date.getMonth(), date.getDate(), 18, 00, 0);
  
  // 完全に業務時間外の予定を省く
  const filteredBlocks = blocks.filter(function(block) {
     return bizStart < block.end && block.start < bizEnd
  });
  
  // 業務時間から溢れた分をカットする
  const cutOffBlocks = filteredBlocks.map(function(block){
    if(block.start < bizStart) block.start = bizStart;
    if(bizEnd < block.end) block.end = bizEnd;
    
    return block;
  });
 
 // 業務時間内で重複を取り除いた予定の合計時間
  var sumMinutes = 0;
  cutOffBlocks.forEach(function(block) {
    sumMinutes += (block.end.getTime() - block.start.getTime()) / (1000 * 60);
  });
  
  const bizMinutes = (bizEnd.getTime() - bizStart.getTime()) / (1000 * 60);
  
  return bizMinutes - sumMinutes;
}

業務時間外を省いているのは、飲み会とかの予定も入ってるから。 休憩時間とかフレックスは未対応です。

もっと効率よく書ける気はしている。

Function App リクエストサイズの上限

Function App に HTTP で Post するときのサイズ上限は web.config でデフォルト値が指定されている。 v1.x では 100MB だそうだ。

azure-functions-host/Web.config at v1.x · Azure/azure-functions-host · GitHub

でも v2.x では指定されてない。

github.com

既定値だと 4MB だけど、この値がそのまま使われるんだろうか??(未検証)

HttpRuntimeSection.MaxRequestLength Property (System.Web.Configuration) | Microsoft Docs

結婚式二次会のBGM #2

3月に友人の結婚式があり、二次会のBGM選曲などを担当しました。

基本的には 3年前に担当したとき と変わらないですが前半の新しめのパートを割と変えました。

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

youtu.be

毒気のない曲を探すのが意外と面倒なわけですが、誰かの参考になれば。

Table Storage は Count できないよ

タイトルのとおりで Table Storage は件数を取得するための API が無い。愚直に全件取得するしかない。 せめてレスポンスを軽くするための手段として、 PartitionKey だけを Select するという手段がある。

var query = new TableQuery<DynamicTableEntity>()
    .Select(new string[] { "PartitionKey" });
var count = table.ExecuteQuery(query).Results.Count;

ただし単発のクエリは最大1000件までしか返ってこないので、セグメント化する必要がある。

var count = 0;
var query = new TableQuery<DynamicTableEntity>()
    .Select(new string[] { "PartitionKey" });
TableContinuationToken token = null;
do
{
    var queryResult = table.ExecuteQuerySegmented(query, token);
    count += queryResult.Results.Count;
    token = queryResult.ContinuationToken;
} while (token != null);

しょっちゅう Count するべきものじゃないんだろうな。

ひとり振り返り

毎週金曜日の夕方に、ひとりで1週間を振り返っています。

手順

  1. その週にあった出来事をA4用紙にひたすら書く。
  2. それぞれ、良かった / イマイチだった、あるいは追加で思うことがあればマインドマップ的に追記していく。
  3. イマイチだったことに対して「この情報が足りないから調べてみよう」など
  4. 良かったことは Keep とする。そのほか、次の週あるいは将来的にやりたいことを Try とする。
  5. 具体的なアクションがあれば個人のタスク管理ツールに転機する。

マインドフルネスでいうジャーナリングというエクササイズに影響を受けています。

紙に書く理由は、気分が振り返りモードに切り替わってる気がするのと、矢印を生やしやすいからです。

タスク管理ツールは、いまは Trello を使っていますが todoist でも紙のふせんでもなんでも良いでしょう。

書く順序は思いついた順。KPTのように良かったことから、というアプローチは特に考えません。良かったことからが効果的なのは、チームでの発言が促進されるからですが、ひとりでやる分にはその観点を考慮する必要はないでしょう。

効果

  • 「頭の片隅にある、なんか気になってるたこと」がたくさんあると個人的にしんどいので、洗い出してタスク管理ツールにまかせられる。脳をデフラグする感覚に近いです。
  • やってる感。

改善したいこと

  • Try がどんどん溜まっていく。。長期的な Planning もどこかでやったほうが良いかもしれない。

Ionic でカスタムコンポーネント

最近 Ionic を触ってハマったのでメモ。

目的 コンポーネント hoge をページ fuga から呼び出す。つまり、 fuga.html に以下のように記述できるようにする。

<hoge></hoge>

はじめます。コマンドからコンポーネントを作成する。

$ ionic g
? What would you like to generate: component
? What should the name be? hoge

/components/components.modules.ts に、作成したコンポーネントへの参照が追加される。なので呼び出し側からはこいつを参照すればよい。

呼び出し側のページを fuga とすると、 fuga.module.ts から下のように参照する。

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { FugaPage } from './fuga';
import { ComponentsModule } from '../../components/components.module'; // 追加

@NgModule({
  declarations: [
    FugaPage,
  ],
  imports: [
    ComponentsModule, // 追加
    IonicPageModule.forChild(FugaPage),
  ],
})

これでも hoge が見つからない旨のエラーが出る時がある。 fuga をモジュールとして扱えていない。app.module.ts

import { Fuga } from '../pages/fuga/fuga'

import { FugaModule } from '../pages/fuga/fuga.module'

とする。さらに、同じく app.module.tsdeclarationsentryComponents などに入っていたらこれらから削除し、 imports に移動する。

晴れて、 fuga から呼び出せる。

<hoge></hoge>

参考:

http://evalogical.com/blog/components-ionic-framework-3

https://stackoverflow.com/a/45032201

カジュアルなビジネス文書でもミスコミュニケーションを減らしたい

最近はビジネスでも Slack とかそのほか社内 SNS とか、カジュアルな文章でのコミュニケーションが増えています。そうした状況ではつい話し言葉的な、ほぼ遂行されていない文章が生まれがち。そうなると要点があいまいな伝え方をしてしまったり、自分の考えがまとまっていないうちに発信してしまったりして、文章のやりとりは多いけど互いに伝えたいことが伝わらない、といったことにつながります。

ここではそうした場において、私が文章を書くときに考えているポイントを述べていきます。

その文章の目的を明確に記述する

文章は、書き手が読み手に何かを要求するもののはず。何か行動してほしい。情報を書き手に教えてほしい。ただ知っていてほしい。これがあることによって、読み手は心構えをした状態で文章を読み始めることができます。冒頭に述べるのがよいでしょう。

目的を明確にできないのであれば、そもそも発信する必要はないかもしれません。

背景や理由を明確にする

これの目的は3つ。

  • 多面的に技術することで、書き手の要求しているものを読み手に伝わりやすくする。
  • 書き手が要求していることが、そもそも見当違いなことだった場合に読み手に気づいてもらう。
    • 特に、読み手のほうがその事情に詳しい場合。
  • 読み手がその先の行動をするためのモチベーションを与える。
    • わけもわからず「これやって」と言われるのは私が嫌なので。

接続詞に気をつける

不用意な接続詞は、読み手の脳のメモリを余分に使ってしまいます。

たとえば日本語で「〜ですが、...」という表現をしたとき、「が」は逆説の場合もあれば順接の場合もあります。どちらなのかを判断するためには、前段の内容を脳のメモリに置きながら後段を読む必要があります。こうなるとコミュニケーションが失敗するリスクが高まります。

また、そもそも使っている接続詞がそのときの前後の論理関係に適していない場合があります。これは、話し言葉においてふだん前後の論理関係を厳密に考えていないためです。

これらを避けるため、私は接続詞を使いたくなったら一文が短くなるように心がけています。「〜ですが、...」と書きたくなったら、逆説であれば「〜です。しかし...」とし、順接であれば、文脈によりますが「〜です。...」とそのままつなげます。

語順に気をつける

話し言葉では思いついた順に単語が発せられがちです。これは頭の中で論理を組み立てながら単語を発しているため。その語順がベストとは限りません。そのままの語順だと、どの単語がどこに掛かっているのか不明瞭で読み手は混乱しがちです。文を読んでみて、伝わりやすい語順になっているかを確認します。

原則としてはやはり英語などのSVOの順序がわかりやすいことが多いでしょう。

形容詞に気をつける

世には「形容詞は使用するな」という過激派もいますが、私は非現実的だと思います。私の考えは、「形容詞を使いたくなったら客観的事実で置き換えられないか検討する」です。可能だったらそれを利用する。そうでなければ、そもそもいま伝えたいことに根拠がないことかもしれない、とか考え直すヒントになります。また、形容詞を除いてしまうと書き手の意図がよくわからなくなってしまう場合もあります。この場合は残すことも検討します。

細かいテク

  • 漢字が連続しないようにする
  • 漢数字/英数字/半角全角 などを統一する
  • 同じ意味の言葉であれば同じ言葉を使う
  • ライトなコミュニケーションでは絵文字を多用する
    • ここまで述べたポイントをおさえると文章から感情が読み取れず威圧感を与えがち。それを抑えるには絵文字が手っ取り早くて有効です😉