Tenka1 Programmer Beginner Contest 2019 に参加した

はじめに

AtCoder競技プログラミングコンテストに初めて参加してみた。

  • HackerRankやcodeIQ(もうサービス終了したんだっけ?)で遊んでいたことはあるが、AtCoderコンテストに参加するのは初めて。
  • 言語はC++を選択。C++チュートリアルを一通りやった程度の知識。

参加したコンテスト

atcoder.jp

A問題

atcoder.jp

  • 提出

github.com

B問題

atcoder.jp

  • 提出

github.com

C問題

atcoder.jp

  • 提出

github.com

D問題

atcoder.jp

  • 時間切れ未提出

感想

  • A, B は特に何も考えなくても愚直にやるだけで解ける問題だった。
  • C問題はちょっと厄介。愚直に全ケース計算しているとタイムアウトする。今回の問題はボーダーを決めて、そこから左側が白、右側が黒になるようにすればいいと気づけるかどうかがポイント。結構時間を取られてしまった。
  • D問題は時間がなく未提出に終わった。
  • 問題自体が小難しいので問題をすばやく理解する読解力も必要。
  • 紙とペンが欲しいと思った。次回は用意したい。

まあ、最初だしこんなもんか。ABCコンテストのDが解けるようになるまでは毎週参加してみたいと思う。

GitFlowでmasterブランチにマージしたあとのrevert作業メモ

想定ケース

  • GitFlowによるdevelop/masterブランチ運用。
  • develop, master ブランチは保護ブランチ。基本的にはGitHub上でのPRベースでマージを行う。

feature ブランチで作業

例として newfile.txt というテストファイルを追加する作業を行う

$ git checkout -b feature origin/develop
$ touch newfile.txt
$ git add newfile.txt
$ git commit -m 'Add newfile'
$ git push origin feature

feature -> develop へマージ

GitHub で developブランチへ向けてPR作成、マージ f:id:tic40:20190408092026p:plain

develop -> master へマージ

f:id:tic40:20190408092230p:plain

master コミットログ。featureブランチで作業したAdd newfile コミットが入っていることを確認 f:id:tic40:20190408092349p:plain

masterブランチでRevertを行う

f:id:tic40:20190408155456p:plain

revertした masterブランチから develop へのマージを行う

f:id:tic40:20190408223141p:plain

ここから再度revertした作業を戻して master にマージする場合

この時点では develop -> master に差分はない f:id:tic40:20190408224024p:plain

revert した内容を revert することで取り消したrevert 内容を developブランチに戻す

$ git checkout develop
$ git log
commit 68ce661756642e444a68d04a32d4cc760bb03510 (HEAD -> develop, origin/develop)
Merge: d666db9 9609193
Author: tic40
Date:   Mon Apr 8 22:30:46 2019 +0900

    Merge pull request #18 from tic40/master

    Merge pull request #17 from tic40/develop

commit 960919320a75a2399e5ea34ebee1305c846e255b (origin/master, origin/HEAD, master)
Merge: 9d2b6c5 5631086
Author: tic40
Date:   Mon Apr 8 22:29:03 2019 +0900

    Merge pull request #19 from tic40/revert-17-develop

    Revert "Release"

$ git revert 9609193 -m 1
[develop 7567e16] Revert "Merge pull request #19 from tic40/revert-17-develop"
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 newfile.txt
$ git push origin develop

これで revert で打ち消した差分を develop に復活、master に再度マージが可能になる f:id:tic40:20190408224229p:plain

Error retrieving access token: TypeError: Cannot read property 'expiry_date' of undefined [clasp]

I encountered an error when I use clasp command as below.

$ yarn clasp create clasp-project --rootDir ./src

yarn run v1.7.0
Error retrieving access token: TypeError: Cannot read property 'expiry_date' of undefined
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I tried re-login and solved it.

$ yarn clasp logout
$ yarn login

github.com

GitHubのissueに特定のラベルが貼られたらSlackに投稿するBOTを作る

特定のリポジトリで、特定のラベルが貼られたらそれを検知してSlackに投稿するBOTをGASで書いた。

github.com

こんな感じにissueに特定のラベルが貼られたら通知を送る f:id:tic40:20181115204625p:plain

やりたかったこと

リポジトリを跨ったアプリケーション構成の場合、Aリポジトリの変更がBリポジトリのアプリケーションに影響を与えることがある。

Aリポジトリに特定のラベルが貼られたら、それをBリポジトリを管理しているチームのSlackチャンネルに通知する、ということをやりたかった。

どうやったか

  • GitHub webhookでラベル変更を検知
  • GASで変更された情報をSlackに投稿すべき内容かどうかチェック
  • GASからSlackにPOSTを投げる

実装手順

GASでスクリプトを書く

claspを使って typescript で記述した。 clasp を使えば、$ yarn clasp push でGASにコードをアップできたり便利。

github.com

  • doPost関数でGitHubのpostを受け取ることができる。
  • 受け取ったらpayloadをチェックする。
  • action プロパティが labeled の場合は新規ラベル追加アクション
  • label プロパティに追加されたラベル情報が入っているので、通知したいラベルかどうかチェック

ソースは以下を参照

https://github.com/tic40/gas-notify-labeled-issue/blob/master/src/index.ts

GASアプリケーションを公開する

GASプロジェクトページからWebアプリケーションとして公開をする。

f:id:tic40:20181115203753p:plain

ここで、現在のWebアプリケーションURLが発行されるのでコピーをしておく

GitHub webhooks を追加する

payload url に先程コピーしたGASアプリケーションのURLをペーストする。 f:id:tic40:20181115204015p:plain

今回hookするイベントは、issues だけで良いので issues のみにチェックを入れる f:id:tic40:20181115204051p:plain

Slack

Incoming WebHooks を通知したいチャンネルに追加する。

WebHook URL が発行されるのでこれもコピーをしておく

f:id:tic40:20181115204307p:plain

GASにスクリプトプロパティの追加

キーや設定情報は、コード内に直接記載せずにGASのスクリプトプロパティに定義している。 SLACK_WEBHOOK_URL などはここに入力している。

const properties = PropertiesService.getScriptProperties()
const SLACK_WEBHOOK_URL: string = properties.getProperty('SLACK_WEBHOOK_URL')
const SLACK_CHANNEL: string = properties.getProperty('SLACK_CHANNEL')
const LABEL_NAME: string = properties.getProperty('LABEL_NAME')
const ICON_EMOJI: string = properties.getProperty('ICON_EMOJI')
const USERNAME: string = properties.getProperty('USERNAME')

GASのプロジェクトページから以下のようにそれぞれ設定を行う

f:id:tic40:20181115204408p:plain

雑感

GAS便利ですね

web componentsについて

web componentsとは何か

Webコンポーネントは、カスタム/再利用可能でカプセル化されたHTMLタグを作成できるWebプラットフォームAPIのセットである。

以下、4つの主要な仕様を持つ。

Custom Elements

Custom Elements

Custom Elementsは、DOM要素を独自に構築する方法を提供する。

Shadow DOM

Shadow DOM

Shadow DOM仕様は、Webコンポーネントカプセル化されたタグを使用する方法を定義する。

ES Modules

ES Modules specification

ESモジュール仕様では、スタンダードベースのモジュール化された方法でJSドキュメントを組み込み、再利用することを定義する。

HTML Template

HTML template element specification

HTML Template仕様では、ページ読み込み時には使用されないが、実行時に後でインスタンス化されるマークアップの断片を宣言する方法を定義する。

demo

custom-btn というカスタム要素を作ってみる

<div>
  <custom-btn></custom-btn>
  <custom-btn>button name</custom-btn>
</div>

<script>
class customBtn extends HTMLElement {
  constructor() {
    super()
    const shadowRoot = this.attachShadow({ mode: 'open' })
    shadowRoot.innerHTML = `
      <button 
        style="background: transparent;">
        <slot>default btn name</slot>
      </button>
    `
  }
}
customElements.define('custom-btn', customBtn)
</script>

demo

See the Pen webcomponents custom btn by tic40 (@ccpzjoh) on CodePen.

ブラウザ対応状況

https://caniuse.com/#search=web%20components

Nuxt.jsにstylelintを導入する

インストールするモジュール

  • stylelint

stylelint.io

  • standard ルールセット

github.com

  • .vueファイル内の<style></style>をパースするために導入する

github.com

インストール

$ yarn add -D stylelint stylelint-config-standard @mapbox/stylelint-processor-arbitrary-tags

設定

プロジェクトディレクトリ配下に、.stylelintrcファイルを作成する

{
  "processors": ["@mapbox/stylelint-processor-arbitrary-tags"],
  "extends": [
    "stylelint-config-standard"
  ]
}

package.jsonにstylelintのscriptを追加する

  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
 +   "lint:css": "stylelint 'src/**/*.vue'",
    "precommit": "npm run lint"
  },

実行

$ yarn lint:css

f:id:tic40:20181015201650p:plain

TIPS

  • scss記法の場合は、オプションで指定できる。 eslint --syntax scss
  • recess-order を入れるとプロパティの宣言順序もチェックしてくれる
  • lintツールに共通して言えることだが、カスタムルールをたくさん追加し出すと後々大変になるので、定番のルールセットを導入してそこからどうしても変えたいものをカスタムルールとして定義する、ぐらいが良い。

Nuxt(Vuex)でAtomic Designを採用するときのメモ

数ヶ月Atomic Designを採用したNuxt(Vuexパターン)アプリケーション開発を行ってみて、思ったことのメモ。

Atomic Designとは

bradfrost.com

概要だけ知りたい人に説明すると、基底となるコンポーネント(原子)を作り、その原子を組み合わせて分子コンポーネントを、さらに分子を組み合わせて有機体コンポーネント、そして最終的にそれらを組み合わせたページを組み上げる、というボトムアップ的アプローチのデザイン手法である。

f:id:tic40:20181007213756p:plain

Nuxt(Vuex)におけるコンポーネント分割方針

Atomic Design手法の肝は、 Atoms/Molecules/Organisms のコンポーネント設計にある。 この設計が抽象的なままだと、アトミックデザインの恩恵は十分に得られない。

コンポーネント設計で、まず最初に頭に入れておきたいのは、

  • Stateless or Stateful
  • 関心の分離

Stateless or Stateful

コンポーネントが状態(data)を持ち、それによって挙動を変える場合はStateful、逆に状態を持たないコンポーネントはStateless。 Statelessにすることで状態による副作用がなくなり、使いやすいコンポーネントになる。 Statelessなコンポーネントでは、watchやmountedといったトリガー、Vuexモジュールへの参照なども副作用を伴うので行わない。

関心の分離

上記を踏まえた上で、Atoms/Molecules/Organismsの設計方針を考える。

Atoms

  • 内部に他のコンポーネントを含まない。ネイティブのHTMLでのみ構成される。
  • 再利用されるコンポーネントである。
  • Statelessである。
  • 単一責任である。
  • Vuexモジュールへの参照は行わない。

Molecules

  • 内部にMolecules以上のコンポーネントを含まない。
  • 再利用されるコンポーネントである。
  • Statelessであることが望ましい。
  • 単一責任である。
  • Vuexモジュールへの参照は行わないのが望ましい。

Organisms

  • 内部にOrganisms以上のコンポーネントを含まない。
  • 再利用性は低くてよい。
  • Statefulである。
  • Vuexモジュールを参照する。

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

Atomic Design ~堅牢で使いやすいUIを効率良く設計する