暗黒エンジニアブログ

株式会社アイネットのエンジニア感があるんだかないんだかよくわからないブログ

ノベルティカンファレンス in 大阪を開催したいなと思っている話 #novecon

f:id:razon:20181027133700j:plain

ご安全に!角田です。

もはやどういう経緯でこんなこといい出したか思い出せないんですが、「ノベルティカンファレンスを大阪でやりたい!」という思いがあったみたいなのでそれに関して書いていきたいと思います。
興味のある方は @razon までご連絡いただけますと僕が大変喜びます。
各位よろしくお願いします。

ノベルティカンファレンスとは?

イベントやセミナー、勉強会で受け取る「ノベルティ」。

「ノベルティ」と一口に言っても、その種類は様々です。 担当者は日夜、何のノベルティにしようか、ロゴはどう入れるか、受け取った人は喜んでくれるのか・・・。 「ポイされたくない」という思いに悩まされていることでしょう。

悩んでいる方もそうでない方も、ノベルティについての思いをたくさんお持ちのことと思います。 そしてその背景には、自社のブランドへの思い、コミュニティへの情熱、受け取る方々への配慮などがあることでしょう。 このイベントでそれを語り合ってみませんか。

という訳でその名のとおりノベルティについて語り合うイベントです。
次回は8/5(月)に東京で開催です!

connpass.com

過去の開催実績

connpass.com

connpass.com

connpass.com

connpass.com

「岡山でもやりたい!」と言い続けたおかげで昨年は岡山開催が実現しました!
この勢いで別地方でも開催できるといいなと思ったから「大阪開催だ!」とか言い出したんだと思います。たぶん。
なんで大阪なのかはすまん、思い出せないんだ…。

募集したいもの

  • 会場を提供していただける企業様
    • 如何せんあまり土地勘もないもので、会場を提供していただける企業様がいらっしゃいましたらめちゃくちゃ嬉しいやつです。
  • 発表してくださる方
    • すごい発表とかでなくて大丈夫です!「こんなもの作ったよ!」とか、「こんな失敗があった…」みたいな、軽めのものでも全然OKです。
  • 作ったノベルティを展示したい方
  • いっそ「イベントの運営やってみたい」という方
  • 「話を聞いてみたい!」という方(5000兆人くらいいてほしい)

開催時期

  • 東京が8月開催なので、秋くらい?(ふんわり、要検討)
    • 平日開催のイメージです

さいごに

個人的には地元開催してとてもよかったイベントなので、是非この輪を広げていきたいと思っています!
ビビッと来た方からのご連絡を心よりお待ちしております!!

2019年度BBQ会を開催しました

f:id:razon:20190511131612j:plain

ご安全に!角田です。

毎年恒例のBBQ会を今年も開催しました。

f:id:razon:20190511115030j:plain
今年も CAMPING EQUIPMENT STORE さんに設営をお願いしています。午前中からかなり日差しが強く、ちょっと心配だったのですが日陰になっており割と過ごしやすかったです。

f:id:razon:20190511115039j:plain
設備がすごい

f:id:razon:20190511120954j:plain
メンバーが集まったので開会宣言です

f:id:razon:20190511123228j:plain 焼きます

f:id:razon:20190511123237j:plain
肉の暴力

f:id:razon:20190511124027j:plain
ケバブ(チョーうまかった)

f:id:razon:20190511125159j:plain
ホタテバターホイル(こんなんまずい筈がないですよね)

f:id:razon:20190511150555j:plain
おい
パイ食わねぇか

f:id:razon:20190511141331j:plain
今年も不穏な文章を読み上げる会が開催されました。
「書いた人の文才がすごい」と評判です。

f:id:razon:20190511150257j:plainf:id:razon:20190511131653j:plainf:id:razon:20190511125220j:plain

f:id:razon:20190511151846j:plain
最後は例のごとく集合写真です。

今年は社内外含め都合が合わない人がそこそこいたのが惜しまれるところなのですが、楽しいひとときを過ごすことができました。 来年もまた開催するので、ご都合よろしければ是非お越しください!

2019年度セキュリティ研修を開催しました

f:id:razon:20190420155231j:plain

ご安全に!角田です。

先週末の4/20(土)に、全社でのセキュリティ研修を開催しました。

例年は社内の会議室を利用していたのですが全社員を入れるにはちょっと手狭になってきたので、今年は倉敷天満屋さんの会議室をお借りして開催しました。

www.tenmaya.co.jp

第一部

第一部はスクール形式での座学になります。 コンテンツは社内のセキュリティ委員会による力作です。

f:id:razon:20190420141323j:plain f:id:razon:20190420142832j:plain f:id:razon:20190420142819j:plain

第二部

第二部はレクリエーション的なコンテンツを行うことが多いのですが、今年はメールの誤送信をしてしまったという設定で実際の規定に沿って報告書を作成するというワークショップを開催しました。 幸い今のところはこういったことを実際に行う機会はなかったのですが、シミュレーション的に運用することで「こういう運用のほうがよいのではないか」「報告書の様式はこうしたほうがよいのではないか」など、様々な意見が出てきて実際に運用してみることの大切さを改めて感じました。

f:id:razon:20190420162255j:plain f:id:razon:20190420162244j:plain f:id:razon:20190420170704j:plain

懇親会

毎年恒例になるのですが倉敷ロイヤルアートホテルさんで執り行いました。

www.royal-art-hotel.co.jp

f:id:razon:20190420180905j:plain f:id:razon:20190420181153j:plain f:id:razon:20190420200029j:plain f:id:razon:20190420200101j:plain

今年は3名の新入社員が新たに増えたので、インタビュータイムです。三者三様でまた新たな一面を見せてくれたのではと思います。

f:id:razon:20190420194112j:plain

最後は一丁締めで無事閉会です。

f:id:razon:20190420201323j:plain

年々この研修の雰囲気がよくなってきているなと感じているのですが、今年は意見の交換なども活発で、より話しやすい空気づくりができている実感がありました。(そのせいでちょっと時間が押し気味になってしまったところもあるのですが…)

来年もより盛会にできるよう、今後も精進していきたいところですね。

#pixela で #めそ子イラストコンテスト のイラストを描いた話

ご安全に!角田です。

めそ子イラストコンテストの締切が近づいてきたので慌てて Pixela でめそ子のイラストを描いたのでその技術的裏側について補足しておこうと思います。

mesoko.jp

ドット絵を描く

Pixelaは基本APIでpixelの値を入れる(色つけ)形なのでそのままではお絵かきには厳しいため、まずはドット絵用のツールでドット絵を描きます。 今回はPiskelを利用しました。はじめての利用だったけど使いやすかった!

www.piskelapp.com

最終的にはPixelaの色しか出せないので、Pixelaのグラフから各色を抜き出してカラーパレットに設定していきます。 色見本のブログがあったのでこれが大変役立ちました。

ryosms.livedoor.blog

描いたドット絵はこちら

Pixelaは縦が7ピクセル、横が50ピクセルちょいなので、7*50で描きました。

www.piskelapp.com www.piskelapp.com

ドット絵のピクセルを読み込んでPixelaに値を登録する

JSで画像をCanvasに読み込んで、1ピクセルずつ読んで色からグラフのquantityに変換してPixelaにAPIで登録していきます。 開始点の日付から1日ずつPixelを読み進めていく感じです。 今回はajisaiとmomijiのカラースキームを使ったのでその対応表を仕込んでいますが、他の色の対応表を作ればその色でいけます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>image2pixela</title>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>  
  <script type="text/javascript">
    // PixelaのAPIキーを指定
    const secret = 'thisissecret'
    // Pixelaのユーザ名を指定
    const userName = 'username'
    const urlBase = `https://pixe.la/v1/users/${userName}/graphs/`
    // Pixelaに登録するグラフと画像のファイル名を一致させる
    const targets = ['akari-saiki', 'hisaki-hanasaki']
    const colors = [{
      // ajisai
      '-10': [71,141,141],
      '-6': [85,170,170],
      '-4': [141,199,199],
      '-1': [199,226,226],
      '0': [238,238,238],
      '1': [234,213,255],
      '4': [213,170,255],
      '6': [170,85,255],
      '10': [106,0,213],
    }, {
      // momiji
      '-10': [106,177,35],
      '-6': [128,213,43],
      '-4': [170,226,114],
      '-1': [213,241,184],
      '0': [238,238,238],
      '1': [255,213,213],
      '4': [255,128,128],
      '6': [255,43,43],
      '10': [255,0,0],
    }]
    window.onload = () => {
      for(let i = 0; i < targets.length; i++) {
        const canvas = document.getElementById(targets[i])
        const ctx = canvas.getContext('2d')
        const img = new Image()
        // 他の画像形式の場合は拡張子調整してください
        img.src = `${targets[i]}.gif`
        img.onload = () => {
          ctx.drawImage(img, 0, 0)
          const data = ctx.getImageData(0, 0, canvas.width, canvas.height);
          const values = getValue(data, colors[i])
          // 基準日の1年前の週の日曜日から描画スタート
          const baseDate = '2019-02-23'
          const endDate = moment(baseDate)
          const startDate = moment(baseDate)
          startDate.subtract(1, 'years')
          startDate.subtract(startDate.day(), 'days')
          values.forEach(value => {
            fetch(
              urlBase + targets[i] + `/${startDate.format('YYYYMMDD')}`,
              {
                'mode': 'cors',
                'method': 'PUT', 
                'headers': {'X-USER-TOKEN': secret}, 
                'body': JSON.stringify({'quantity': value})
              }
            ).catch((error) => console.error(error))
            console.log(startDate.format('YYYYMMDD') + ':' + value)
            startDate.add(1, 'days')
          })
        }
      }
    }
    function getValue(data, colors) {
      const values = []
      for(let i = 0; i < data.width; i++) {
        for(let j = 0; j < data.height; j++) {
          var idx = (i + j * data.width) * 4
          Object.keys(colors).forEach(key => {
            const value = colors[key]
            if (data.data[idx] === value[0] &&
                data.data[idx + 1] === value[1] &&
                data.data[idx + 2] === value[2]) {
              values.push(key)
            }
          })
        }
      }
      return values;
    }
  </script>
</head>
<body>
  <canvas id="akari-saiki" width="50" height="7"></canvas>
  <canvas id="hisaki-hanasaki" width="50" height="7"></canvas>
</body>
</html>

画像を読み込んでCanvasに叩き込むのにセキュリティ的な制限があるためローカルでは動作しないので、何かしらのWebサーバを立ち上げて動かす必要があります。 画像ファイルはHTMLと同じパスに置きます。 なお読み込んだだけでそのままPixelaのAPIを叩きに行くアグレッシブな仕様です。

できあがったものがこちらになります

https://pixe.la/v1/users/razon/graphs/akari-saiki?date=20190223 https://pixe.la/v1/users/razon/graphs/hisaki-hanasaki?date=20190223

みんなもPixelaでお絵かきしてみてくれよな!

SUZURIのPixela Shopをそれっぽい感じにする

ご安全に!角田です。

Pixela Shopができましたね!

blog.a-know.me

ただちょっと気になってて、

ということなので、雑にGreasemonkeyを書いて解決していきます。

Greasemonkey - Wikipedia

できあがったものがこちらになります

gist.github.com

いい感じですね。
そんな訳でこのエンジニアブログも今年最後な気がするので、みなさまよいお年を!

あわせて読みたい

twilog.org

GASでつくる #Backlog 警察

ご安全に!角田です。

このエントリは、Backlog Advent Calendar 2018の26日目(勝手にやっているだけ)です。

adventar.org

この記事でやること

先の記事 でGAS使って興が乗ったので、ついでに期限切れのタスクをSlackに通知するBacklog警察もGASで実装してしまおうと思います。
よろしくお願いします。

🔑BacklogのAPIキー発行

個人設定 - API から、Backlog警察用のAPIキーを発行します。管理用のユーザとかでやるのが無難でしょうか。

backlog.com

🖇SlackのIncoming Webhook設定

SlackのアプリにIncoming Webhookを追加します。

f:id:razon:20181225104434p:plain
f:id:razon:20181225104808p:plain
f:id:razon:20181225104810p:plain
f:id:razon:20181225104811p:plain
WebhookのURLができました。

💨GASを書く

function BacklogPolice() {
  var response = fetchBacklogIssues();
  postSlack(JSON.parse(response));
}

var backlogNamespace = 'your_backlog_namespace';
var backlogUrl = 'https://' + backlogNamespace + '.backlog.jp/';

function fetchBacklogIssues() {
  var baseUrl = backlogUrl + 'api/v2/issues';
  var apiKey = 'your_backlog_api_key'
  // 取得対象のプロジェクトIDのリストを指定
  var projectIds = [n];
  var statusIds = [0, 1, 2, 3];
  var sysdate = new Date();
  sysdate.setDate(sysdate.getDate() - 1);
  var params = {
    'apiKey': apiKey,
    'dueDateUntil': formatDate(sysdate)
  };
  for (var i = 0; i < projectIds.length; i++) {
    params['projectId[' + i + ']'] = projectIds[i];
  }
  for (var i = 0; i < statusIds.length; i++) {
    params['statusId[' + i + ']'] = statusIds[i];
  }  
  var paramString = '';
  for (var key in params) {
    if (0 < paramString.length) {
      paramString += '&';
    }
    paramString += key + '=' + params[key];
  }
  return UrlFetchApp.fetch(baseUrl + '?' + paramString);
}

function postSlack(issues) {
  if (issues.length <= 0) {
    return;
  }
  var baseUrl = 'your_slack_incoming_webhook_url';
  var headers = {
    'Content-Type': 'application/json'
  };
  // ここはお好みでいい感じにカスタマイズしてください!
  var params = {
    'channel': '#backlog_notify',
    'username': 'Backlog警察',
    'icon_emoji': ':backlog:',
    'text': createPostMessage(issues),
  }
  var options = {
    'method': 'POST',
    'headers' : headers,
    'payload': JSON.stringify(params)
  };
  UrlFetchApp.fetch(baseUrl, options);
}

function createPostMessage(issues) {
  var message = '<!channel> Backlogのタスクが期限切れになっています!速やかにタスクを処理するか、期限日を調整してください。\n';
  for (var i = 0; i < issues.length; i++) {
    var issue = issues[i];
    message += '[' + issue.issueKey + ']: ';
    message += '<' + backlogUrl + 'view/' + issue.issueKey + '|' + issue.summary + '>';
    message += '[' + issue.status.name + '], ';
    message += formatDate(new Date(issue.dueDate)) + ', ';
    message += issue.assignee.name + '\n';
    return message;
  }
}

function formatDate(date) {
  var format = 'YYYY-MM-DD';
  format = format.replace(/YYYY/g, date.getFullYear());
  format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
  format = format.replace(/DD/g, ('0' + date.getDate()).slice(-2));
  return format;
}

🔫GASのトリガーを追加

f:id:razon:20181225110056p:plain
f:id:razon:20181225110058p:plain
f:id:razon:20181225110100p:plain

💪できあがったものがこちらになります

f:id:razon:20181226091752p:plain

よかったですね。
いやよくないですね。あまりBacklog警察にはお世話になりたくないものです!

合同勉強会 in 大都会岡山 -2018 Winter- & 忘年会議2018を開催しました #gbdaitokai #忘年会議

ご安全に!角田です。 2018/12/22(土)に、年末恒例の「合同勉強会 in 大都会岡山 -2018 Winter-」「忘年会議2018」を開催しました。

gbdaitokai.connpass.combonenkaigi.connpass.com

当日の様子や資料なども公開されているので、是非ご覧になってみてください。

togetter.com gbdaitokai.connpass.com

話したこと

Vue CLI が生成したプロジェクトの雛形から、Vue CLIの内側を読み解いていく、みたいな話をしました。
本来のプランであればVueめっちょできるおじさんが場にいて、ツッコミが入りながら皆で理解を深めていければいいなあという目論見があったのですが、みなさんシャイなのかあまりそういうのがなかったのが悔やまれるところでした。

平成30年7月豪雨岡山県災害義援金と平成30年北海道胆振東部地震災害義援金について

先日の合同勉強会 in 大都会岡山 -2018 Summer-に引き続き、災害義援金の募金を募ったのでした。

inet-engineer.hatenablog.com

今回は7月豪雨と北海道地震に半分ずつ寄付してきました。

私の 煽り 呼びかけに応じて募金してくださったみなさま、本当にご協力ありがとうございました。

最後に

岡山での年末恒例となっている当イベントですが、運営がコンテンツを作り込むというより、「みんなで一緒に作り上げていく」という点を重視しています。(運営側が無理なくできる、というところを狙っている面もあります)
毎年多くの方にお越しいただきまして、今年も参加者100人を超える規模になってきたにも関わらず大きなトラブルもなく無事に開催できているのは、毎年発表枠に申し込んでくださったり、足を運んでくださる皆様の多大なるご協力あってのことです。
毎年のことになりますが本当にありがとうございます。

あと今年は運営メンバーを公募したのですが、おかげ様で色々とスムーズに運営することができました。
スタッフの皆様も本当にありがとうございました。
(「来年はスタッフやりたい!」という人は声掛けしてくれていいのよ!)

また来年も開催するので、引き続きご協力いただければ幸いです。
重ねてになりますが、皆様本当にありがとうございました!