業務中でも堂々とサボってSlackのtimes文化を満喫したい

(。ì _ í。) < この記事は 𝕂𝔸𝕐𝔸ℂ 𝔸𝕕𝕧𝕖𝕟𝕥 ℂ𝕒𝕝𝕖𝕟𝕕𝕒𝕣 𝟚𝟘𝟚𝟘 25日目の記事です




はじめに

どーも、こんにちは! 20年度新卒の色物枠のakipakaです、waiwai。 ぼくらの甲子園ポケットというソーシャルゲーム(通称:ぼくポケ)のサーバーサイドやっとります!!

備忘録として僕が新卒研修のときに作ったものについて書きたいと思います!

ところで僕は根がとても不真面目な人間なので、業務中にslackを眺めては無為に時間を過ごしサボっている訳ですが、入社1ヶ月と立たないうちにclubだのtimesだの余りにチャンネルに入り過ぎて手に負えないと言う自体に陥りました。


times 分報って何!?ってなった方にオススメの記事

https://giginc.co.jp/blog/news/slack-hunho


ひとまず原因を分析しながら小首を傾げて唸っていました。

なぜ追えないのか僕なりにその理由について考えてみました。


1. チャンネルの更新スピードが早すぎる、秒速5センチメートル位の更新頻度。
2. 一気に沢山のチャンネルに入りすぎた、人間関係を気にすると抜けられない豆腐メンタル。
3. 僕がわるいんじゃあない、みんなのtimesが面白過ぎるのだ。


結論:やっぱり1つのTLで見たいときに見ればいいtwitter最高なんだなぁ。


そこで一つの考えにたどり着く、slackをtwitterみたいに1つにまとめちゃえばいいぢぁん。

""破壊的な発想""

頭の中のジャニー喜多川が言う。「YOUやっちゃいなよ」

んで新卒研修のときに一緒に作りたいと言ってくれたmiyabin君とともに実装に取り組みました。主にakipakaがDB周りのAPI実装(akipakaAPI)を、miyabinがIO周りのAPI実装(miyabinAPI)に取り組みました。研修の1週間だけでなくちょいちょいプライベートでも取り組み、約1ヶ月弱で以下のようなものを実装することが出来ました。

概要


f:id:mamepon2580:20201224103914p:plain


TimesLineという、連携されたtimesにあった投稿を同期して、1つのchannelに表示できるアプリケーションを作りました。アイコンなどは固有のuserのものになっていますが実際はbotが投稿しています。timeslineでは名前の横に投稿された元のtimes名が表示されます。>マークをクリックすると元のtimesでの投稿に飛ぶことが出来ます。

f:id:mamepon2580:20201224103855p:plain

こんな感じ

技術構成

使った技術はこんな感じです。当時はあんまりDocker慣れしてなかったのでVM使ってローカルに立ててそれをherokuに乗っけてデプロイしました。PostgreSQLの設定に苦しめられた苦い思い出。SlackのAPIをゴリゴリ使い倒して作ってます。

f:id:mamepon2580:20201224103905p:plain

DBの設計

めっちゃ簡素でslack上にはchannel同士を連携するrelationとpost,threadなどの投稿を同期するpost_relation、thread_relationから出来ています。それぞれがchannelの中にpostが、postの中にthreadがあるのでそれぞれ1:nの関係になっています。

f:id:mamepon2580:20201224103902p:plain

機能

機能は大きく分けて3つあります

  1. channel同士を連携する機能
  2. 連携されたchannelの投稿を同期する機能
  3. 同期されたpostの中のthreadを同期する機能

またmessegeとpictureなどを投稿でき、それぞれにpost(投稿)、edit(編集)、delete(削除)の同期を実装しています。

timesをtimeslineへ連携する機能

#times ⇒ #timesline​
channel,

timesからtimeslineへの投稿

#times ⇒ #timesline​
post, thread,

timeslineからtimesへの投稿

timesline ⇒ #times
thread,

投稿できる内容

messege, picture

投稿に対する処理

post, edit, delete

よく見るとtimesline ⇒ timesではthreadしか投稿できるようにしていないのですが、これは色んな人が入り混じってるtimeslineの投稿が自分のtimesに流れて来ないようにする為です。ただしthreadはpostに対してつくものなので、自分のtimesのpostと連携されたtimeslineのpostにthreadがついた場合にのみ元のtimesのpostにも投稿するという形をとっています。難しい事を言っている。

設計

機能が多いので3つだけ設計の詳細を説明したいと思います。

分岐部分

slackから受け取った情報を受け取り処理によって分岐させる部分の設計です。ここでchannel同士を連携するbotコマンドやpost,threadに対するpost,edit,deleteなどの処理を分岐しAPIに渡していきます。

f:id:mamepon2580:20201224103856p:plain

timesからtimeslineへのpostの同期

連携されたtimesでpostの投稿が行われ発火が起こるとそれを分岐にかけて分別し、relation/searchのAPIにid渡します。そこで連携されているすべてのtimeslineのidを探し出し、それぞれにtimesline/throwに渡し投稿させていきます。その後でtimeslineの投稿されたpostのidを取得し、timesのpostとtimeslineのpostのidをDBに記述します。

f:id:mamepon2580:20201224103849p:plain

timeslineからtimesへのthreadの同期

こちらはtimesからtimeslineのpostの同期と比較するとかなり複雑です。timeslineからtimesへのthreadの同期なので子→親→子のように同期していく必要があるからです。ここではtimeslineのidとtimeslineに投稿されたpostのidでtimesのidとpostのidを見つけだしtimesに投稿します。そして、元々投稿のあったtimesline以外のtimeslineにも同期させます。

f:id:mamepon2580:20201224103911p:plain

連携されたtimeslineでthreadの投稿が行われ発火が起こるとそれを分岐にかけて分別し、post_relation/detectのAPIにid渡します。そこで連携されているtimesのidを探し出し、それぞれにtimes/throw_threadに渡し投稿させていきます。その後でtimeslineの投稿されたthreadのidを取得し、timesのthreadとtimeslineのthreadのidをDBに記述します。そのままpost_relation/syncを叩き「timesからtimeslineのpostの同期」と同じように他のtimeslineにもthreadを投稿していきます。

f:id:mamepon2580:20201224103852p:plain

まとめ

使ってみて最高かよって感じ。いろんなチャンネルピコピコ光ってるけどぶっちゃけtimeslineだけ見てれば全部追えるし、入ってるtimesで話してる内容にもリンク機能で飛んでいけるのでwaiwai絡んでいけるし。すばらしみ。今回は実験的に作った感じでherokuのDBいっぱいになって使えなくなっちゃったけど、作り直してtimeslineライフ満喫してQOL上げてきたいです!

チーム開発においてだと、設計は僕が作りましたがSlackのAPIの調査などはmiyabinに任せきりだったので、上手く連携を取りながら分担して進められたかなと思います。実際今配属されているぼくポケの開発でも、ここまで役割分担を気にしなけれいけないことはそれほどないのでいい経験できたかな。そして何より、2人でこういう機能があったらいいねっていう機能のアイデアを出してそれいいねって言い合えるのがすごく楽しかった。一緒に作ってくれてmiyabinありがとう。感謝。

今すぐ使える?!クリスマスイブっぽいイージング関数を作ってみよう!

Tech KAYAC Advent Calendar 2020 24日目の記事です。


こんにちは!

カヤック意匠部アートディレクターの おばら です。

今日はクリスマスイブということで

イブっぽい「イージング関数」を作ってみようと思います。

f:id:tsmallfield:20201224013617g:plain
EaseInSineChristmasTree

まずはイージングについて軽くおさらい。

「In」「Out」「InOut」?

f:id:tsmallfield:20201223144728p:plain

「In」「Out」「InOut」(「OutIn」)はイージングカーブの曲がり具合。

  • 徐々に傾きが大きくなっていくなら「In」

  • 徐々に傾きが小さくなっていくなら「Out」

ふむふむ。

位置の時間経過のアニメーションに使うとしたら

  • だんだん早くなるなら「In」

  • だんだん遅くなるなら「Out」

と。

「Sine」「Cubic」「Circ」、、?

イージング関数がどんな計算式で作られているかが名前で分かる場合もあります。

-「Sine」なら y = sin(x)

-「Cubic(Power3)」なら3次関数 y = x3

-「Circ」なら円、 x2 + y2 = 1

という具合。

いろんな作り方があるんですね。

(環境によってはベジェ曲線で指定する方法も)

EaseInSine を作ってみる

まずは練習。

EaseInSine を作ってみましょう。

「Sine」、つまり y = sin(x) を考えます。

y = sin(x)

y = sin(x)

グラフまで表示してくれるなんて、Google検索便利すぎです。

「In」になっている部分を探すと。。

f:id:tsmallfield:20201223133038p:plain

あった!

これを

x = 0 のときに y = 0

x = 1 のときに y = 1

となるよう調整していきます。

縦軸Yをあわせる

上(+方向)に 1 ずらします。

y = sin(x) + 1

f:id:tsmallfield:20201221234647p:plain

y が 0〜1の範囲になりました。

横軸Xをあわせる

横方向にギュッと縮め、

右(+方向)に π/2、つまり 90° ずらします。

y = sin(x * π/2 - π/2) + 1

f:id:tsmallfield:20201223133514p:plain

できた!

JavaScript で書くと、

function easeInSine(x) {
    return Math.sin(x * Math.PI / 2 - Math.PI / 2) + 1;
}

ちょっとだけリファクタリング

実は sin(x - π/2) は -cos(x) と同じ。

つまり

y = sin(x * π/2 - π/2)

y = -cos(x * π/2) + 1

と書き直せちゃいます。

つまり、

function easeInSine(x) {
    return -Math.cos(x * Math.PI / 2) + 1;
}

- Math.PI / 2 がなくなった分シンプルになりました。

答え合わせ

よく使われていそうなライブラリの実装と比較してみます。

jQuery.easing の EaseInSine

https://github.com/gdsmith/jquery.easing/blob/master/jquery.easing.js#L102-L104

easeInSine: function (x) {
    return 1 - cos( x * PI/2 );
},

同じ!

GSAP の EaseInSine

https://github.com/greensock/GSAP/blob/147a6b6594d6bf272ab74ddbbbb2060190c6cce5/src/gsap-core.js#L1046

_insertEase("Sine", p => p === 1 ? 1 : -_cos(p * _HALF_PI) + 1);

同じ! (GSAPは In をベースにそれを反転したりくっつけたりして Out, InOut を生成しています)

https://github.com/greensock/GSAP/blob/147a6b6594d6bf272ab74ddbbbb2060190c6cce5/src/gsap-core.js#L988

_insertEase = (names, easeIn, easeOut = p => 1 - easeIn(1 - p), easeInOut = (p => p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2)) => {

easeOut = p => 1 - easeIn(1 - p)
easeInOut = (p => p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2)

の部分で(easeOut, easeInOut が明示的に指定されない場合は)ゴニョゴニョしてますね!

EaseOutSine, EaseInOutSine も作ってみる

EaseOutSine

y = sin(π * x / 2)

f:id:tsmallfield:20201222002913p:plain

function easeOutSine(x) {
    return Math.sin(Math.PI * x / 2);
}

EaseInOutSine

y = (sin(πx - π / 2) + 1) / 2

f:id:tsmallfield:20201223133843p:plain

function easeInOutSine(x) {
    return (Math.sin(Math.PI * x - Math.PI / 2) + 1) / 2;
}

Math.cos() で書き直すと

function easeInOutSine(x) {
    return (1 - Math.cos(Math.PI * x)) / 2;
}

N次関数系も作ってみる

1次関数でつくるイージング(Linear, None)

まずは基本の1次関数(Linear function)

y = x

f:id:tsmallfield:20201223134118p:plain

function linear(x) {
    return x;
}

2次関数でつくるイージング(Quad, Power2)

2次関数(Quadratic Function)

つまり

xの2乗(x to the power of 2)

y = x2

f:id:tsmallfield:20201222004012p:plain

function easeInQuad(x) {
    return x**2;
}

もしくは

function easeInQuad(x) {
    return x*x;
}

もしくは

function easeInQuad(x) {
    return Math.pow(x, 2);
}

など。

Math.pow()powpowerpow だったんですね。)

3次関数でつくるイージング(Cubic, Power3)

3次関数(Cubic Function)

xの3乗(x to the power of 3)

y = x3

f:id:tsmallfield:20201223134357p:plain

function easeInCubic(x) {
    return x**3;
}

もしくは

function easeInCubic(x) {
    return x*x*x;
}

もしくは

function easeInCubic(x) {
    return Math.pow(x, 3);
}

など。

どんどんカーブが急になっていきますね。

0.25乗とか、0.5乗 とかも面白そうです。

円(Circ)

円の式は

1 = x2 + y2

変形して1上にずらすと

y = -sqrt(1 - x2)+1

f:id:tsmallfield:20201223134641p:plain

function easeInCirc(x) {
    return -Math.sqrt(1 - x**2)+1;
}

グラフにしてみる

EaseInSine を Canvas 2D でグラフにしてみました。

1) 自作版

See the Pen Drawing Easing Curve: EaseInSine by Tohl SMALLFIELD (@tsmallfield) on CodePen.

2) jQuery.easing.easeInSine

See the Pen Drawing Easing Curve: jQueryEasing EaseInSine by Tohl SMALLFIELD (@tsmallfield) on CodePen.

3) GSAP Sine.easeIn

See the Pen Drawing Easing Curve: GSAP EaseInSine by Tohl SMALLFIELD (@tsmallfield) on CodePen.

同じですね。

アニメーションしてみる

自作したEaseInSine関数でなにか動かしてみましょう。

ミニマムなサンプルコードを用意しました。

See the Pen Preview Easing: EaseInSine by Tohl SMALLFIELD (@tsmallfield) on CodePen.

いい感じですね。

「In」ではなく「Out」にするともっと気持ちよくなりそうです。

イブっぽいイージング関数を作ってみる

さて、お待たせしました。

ようやく本題です。

イージング関数の作り方がわかったので

ちょっと遊んでみます。

EaseInSineChristmasTree

EaseInSine (と Circ)で作ったクリスマスツリーです。

諸事情により倒れたクリスマスツリーとなっております。

See the Pen Drawing Easing Curve: EaseInSineChristmasTree by Tohl SMALLFIELD (@tsmallfield) on CodePen.

3歩進んで2歩下がる的な。

そもそも目標値に到達してくれません。

とんでもないイージング関数です。

使い所はあるんでしょうか。

とりあえずアニメーションに使ってみましょう。

1) アニメーション機能含めフルスクラッチ版

See the Pen Preview Easing: EaseInSineChristmasTree by Tohl SMALLFIELD (@tsmallfield) on CodePen.

2) jQuery.animate() + 自作イージング関数

See the Pen Preview Easing: EaseInSineChristmasTree + jQuery.animate() by Tohl SMALLFIELD (@tsmallfield) on CodePen.

3) gsap.fromTo() + 自作イージング関数

See the Pen Preview Easing: EaseInSineChristmasTree + gsap.fromTo() by Tohl SMALLFIELD (@tsmallfield) on CodePen.

じゃじゃ馬ですね。。

EaseOutSineChristmasTree

「Out」だと。。

See the Pen Drawing Easing Curve: EaseOutSineChristmasTree by Tohl SMALLFIELD (@tsmallfield) on CodePen.

EaseInOutSineChristmasTree

「InOut」だと。。

See the Pen Drawing Easing Curve: EaseInOutSineChristmasTree by Tohl SMALLFIELD (@tsmallfield) on CodePen.

EaseOutQuartChristmasTree

jQuery.easing の easeOutQuart を使うと。。

See the Pen Drawing Easing Curve: EaseOutQuartJQueryEasingChristmasTree by Tohl SMALLFIELD (@tsmallfield) on CodePen.

串にささった鏡餅にも見えてきました。

EaseInBounceChristmasTree

GSAPの Bounce.easeIn を使うと。。

See the Pen Drawing Easing Curve: EaseOutElasicGSAPChristmasTree by Tohl SMALLFIELD (@tsmallfield) on CodePen.

もうなにがなんだかわかりません。

まとめ

いかがでしたでしょうか?

既存のイージングだけでは細かいニュアンスを表現できないこともあるかと思います。

そんなときは

イージング関数のパラメータを調整したり、

もしくは0から自作したりしてみてください。

既存のイージング関数をいくつか足したり掛けたりしても面白いかもしれません。

表現の幅が広がります。

それでは良いクリスマスを!

参考リンク

robertpenner.com

easings.net

design.kayac.com