pco2699’s blog

学んだコード・技術について、保存しておく場所

Nimで変数の型を調べる

本日からNimデビューしたのでNimのつまずいたところをメモっておく

Nimで変数の型を調べる

なんとtypetraitsという標準パッケージをimportする必要がある、とのこと。  

import typetraits

var hoge = 10
echo hoge.type.name

これで

int

と出ます。おしまい。

Yahoo! Hack Day 10th Aniv. に参加してHack賞 受賞しました!!

12/9(土)-12/10(日)で開催されたYahoo! Hack Day 10th Aniv.に参加してきました!! そしてまさかのHack 賞 受賞!

ハッカソンは今まで何回も出場してきましたが、まともに賞をゲットできたのは
初めてで、ひっじょおううに嬉しいので本ブログに思い出を綴っていきます。

正直、当日も大変だったのですが、一番苦労したのがアイデア出し、 でした。
そこの部分をメインで書かせていただきます。
(気が向いたら技術編も書きます...)

つくったもの

電車でどこで降りるかを超音波通信で知れるWebアプリ、なるものを作りました。
題していすとりSonicです。 f:id:pco2699:20171213002216p:plain

内容は以下のプレゼンを見ていただくとわかりやすいかと思います。
https://youtu.be/1Nlm69tcuak?t=13539

これができた経緯

この作品ができた経緯を、チーム結成から振り返りたいと思います...笑

2ヶ月前 チーム結成

私を含めたメンバ全員、ジーズアカデミーというプログラミングスクールを10月に卒業し
その中のメンバで意気投合し、ハッカソンにでよう!、という話になりました。

ちなみに、ジーズアカデミーは最高なプログラミングスクールなので
みなさん、ぜひ入ってください。
いろんなバックグラウンドの人がいて、めっちゃ面白いです。 gsacademy.tokyo

1ヶ月前 アイデア出し・技術調査

初めてのHack Dayのため、みんなで前回のHack Dayの発表動画を穴が空くほど見ました。
どれも技術力・実装力がめちゃくちゃすごい作品ばっかりで
メンバ間でも「これ、いけんのか笑」的な感じでした。

www.youtube.com

それでも出るからには最優秀賞!ということで技術をベースにしてアイデア出しや技術調査をめっちゃしました。
ただ、まともなアイデアは出てこず、あっというまに1週間前になります...

1週間前 アイデア出し

企画会議で、最初は「ARKit出たからARアプリつくりたいよね〜」って感じで ARアプリを考えていました。
それで電車の降りる人がARでわかったらおもろい、というネタが出てきました。

その時のデザイナさんが書いてくれたイメージはこんな感じ↓ f:id:pco2699:20171213002805p:plain

5日前 技術調査・フィージビリティ調査

ただ、「電車AR」は一つ、問題があることがわかりました。
電車は移動しているからGPSの位置情報が使えない、ということです。
当たり前ですが...

知らない人と端末間通信をするときは

  • 位置情報
  • BLEビーコン

が主流。ですが

  • 位置情報→移動しているので☓
  • BLEビーコン→正確な場所わからない

ということで 、かなり積んだ感じとなってしまいチーム内の空気が重苦しくなりました...

4日前〜1日前 企画会議

ここから、ヤバイということになり仕事終了~終電まで、毎日 企画会議をすることに。

そんな時に自分がふと思い出したのが、このアプリ hacklog.jp

このアプリを見たときから超音波通信!とは思ってましたが
この超音波通信は、電車内の匿名通信に使えるのでは?とふと思いつきました。

ARは無理そうなので、超音波を意識したUIをデザイナに考えてもらい これで当日行くことになりました。

ただ、これって本当に電車をHackできてるわけじゃないよね?と納得できていないメンバもおり
なんとなくもやもやした状態でHack Dayを迎えることになります。

Hack Day 当日 1日目

前日のもやもやが続いており、ネーミングでそれが噴出しました。
自分が思いつきで SuperSonicニコニコ電車(超適当)でよくね!?と言ったら
デザイナの方がそのネーミングだとロゴが書けないとなり、提出期限の夜10時まで、ギリギリまで悩んでました。

ただ、自分はフロント実装担当だったので
途中からネーミング考えるのは放棄して実装に集中しました笑
そしたら「いすとりSonic」という名前で納得したようで、ネーミング決定と相成りました。

Hack Day 当日 2日目

やはりというかなんというか、他のプロダクトが凄すぎて
メンバと、「来年、もっと実装力をつけて頑張ろう」とプチ反省会を開くぐらいでした。

個人的に、凄いと思ったのは、

  • 最優秀賞の「とるだけ!ユーチューバー」
  • アプリだけでモノの重さが測れる「Weight Memo」
  • スマートスピーカーをハックした「スマートスピーカー2.0」などなど...

(ってかモノが出来ませんでした〜、って言ってるところが無いのも普通に凄いよなって思います。)

そんな中で、Hack賞を貰えたのは本当にありがたい話です。
これはひとえに、チームメンバが各々の度量を最大限に発揮した結果だと思ってますし
ホントチームメンバの方には、一生 頭が上がりません。

ただ、この受賞で慢心せず 新人賞をもらったと思って 来年以降のHack Dayは更にレベルアップして頑張っていきたいと思います!

GrovePiの実装を実機テストなしでできてしまうGrovePiエミュレータの使い方

言いたいこと

Groveってはんだ付けなしでセンサがつくれて便利…!
GrovePiってGroveセンサをRasPiに繋げられて更に便利..! でも、GrovePiをつかったプログラムを組むとき、わざわざ実機テストするのはめんどくさい…!
と思っていたら、こんな便利なGrovePiエミュレータがありました。
(GrovePi自体はNodeやJavaでも動きますが、本エミュレータPythonでしか動かないようです…!)

github.com

使い方

基本 Macでの使用を前提しています

GrovePiエミュレータをgitからもってくる

$ git clone https://github.com/joemarshall/grovepi-emulator.git

GrovePiエミュレータを立ち上げる

$ cd grovepi-emulator
$ python grovepiemu.py

そうするっとアッラー素敵なGUIが立ち上がります
f:id:pco2699:20170806195013p:plain

GrovePi用のPythonスクリプトの実行

Pythonスクリプトを以下の「Load…」部から指定すると
GUIで指定したセンサの値が入力されている前提で、エミュレータが動いてくれます。
f:id:pco2699:20170806195124p:plain

動かすスクリプトは以下の通り、GrovePiのライブラリをimportした 前提で実装すれば、エミュレータがよしなにやってくれるみたいです

import grovepi
import time

if __name__ == '__main__':
    while True:
        input = grovepi.analogRead(0)
        print(input)
        time.sleep(1)

Pythonでインスタンスメソッドの中で、宣言した変数はインスタンスメソッド内限定の変数となる

言いたいこと

Pythonのクラスの作り方はわかりづらい。
クラス変数とインスタンス変数、普通の関数内変数がどのように扱われるかがわからない!
ということで、以下のようなテストコードを書いてみた。

基本的には、以下の理解でよいみたい

  • selfをつけるとインスタンス変数
  • classの直下で宣言された変数はクラス変数
  • 各メソッド内で宣言された変数は関数内変数

コード

 -*- coding: utf-8 -*-

class Hoge():
    hoge = "私はクラス変数としてのhoge" #これはクラス変数として扱われる

    def __init__(self):
        self.hoge = "私はインスタンス変数としてのほげ" # selfをつけるとインスタンス変数
        hoge = "私はinit関数内としてのほげ" # これはinit関数内限定の変数

    def test(self):
        hoge = "私はインスタンスメソッドの中のほげ"  # test内関数の変数
        print(hoge) # -> 私はインスタンスメソッドの中のほげ
        print(self.hoge) # -> 私はインスタンス変数としてのほげ

    @classmethod
    def test_cls_hoge(cls):
        print(cls.hoge) # -> 私はクラス変数としてのhoge

def main():
    hoge = Hoge()
    hoge.test()
    Hoge.test_cls_hoge()

if __name__ == '__main__':
    main()

Vue.jsで簡単なタイマーアプリ

つくりましたよ

Vue.js/Moment.jsで簡単なカウントダウン日付タイマーをつくりました

コード

js部

import moment from 'moment'
import Vue from 'vue'

let now_date = moment()

let date_format = 'YYYY:MM:DD HH:mm:ss'

let submission_date = moment('2017-09-22 23:59')
let presentaion_date = moment('2017-10-12 23:59')

const vm = new Vue({
  el: '#date',
  data: {
    now_date: now_date.format(date_format),
    submission_remain_days: now_date.diff(gga_submission_date, 'days'),
    presentaion_remain_days: now_date.diff(gga_presentaion_date, 'days')
  },
});

setInterval(()=>{
  vm.now_date = moment().format(date_format)
},1000)

html部

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello Vue</title>
  </head>
  <body>
    <div id="date">
      <div class="row">
        <span class="label">現在日付:</span> <span class="data">{{now_date}}</span>
      </div>
      <div class="row">
        <span class="label">提出締切: </span> <span class="data">{{gga_submission_remain_days * -1}} </span>
      </div>
      <div class="row">
        <span class="label">発表: </span> <span class="data">{{gga_presentaion_remain_days * -1}} </span>
      </div>
    </div>
    <script src="dist/bundle.js"></script>
  </body>
</html>

つまづきポイント

現在の日付を書き換えるのに、

let now_date = moment()

const vm = new Vue({
  el: '#date',
  data: {
    now_date: now_date.format(date_format), // ここでnow_dateをvmのdata部に設定
    submission_remain_days: now_date.diff(gga_submission_date, 'days'),
    presentaion_remain_days: now_date.diff(gga_presentaion_date, 'days')
  },
});

setInterval(()=>{
  now_date = moment().format(date_format) // 間違えてnow_date側のオブジェクトを取得しちゃっている...
},1000)

と、vueのdata部じゃなくて、設定するオブジェクト側を書き換えてたんだけど
もちろんこれは誤りで、ちゃんと、vueのdata部をsetInterval内で書き換えるようにしたらいけました。
(すごいシンプルな間違い。)

シンプルにView(html)とModel(js)をバインディングしてくれて非常に楽ですね〜
(ReactとかRiotとか使ったことないので、もっと楽かもだけど。)

Date型から強制的に「年月日」以外のデータを切り捨てる

環境

つまづきポイント

Swiftで日付の差分を計算してその間の日数を表示するロジックを書いてたら Date型で時・分が保存されてしまっていて、想定外の日数となっていた!

// 現在日付を取得(例えば 2017/07/12 12:01)
let today_date = Date()
// 期限を取得(例えば 2017/07/22 12:00)
let deadline_date = settings.object(forKey: "deadline_date") as? Date
    
// 現在の残り日数を計算
var deadline_days_now = calendar?.dateComponents([.day], from: today_date, to: deadline_date).day
// ->日付だけ計算すると10日のはずだけど、時・分が保存されてしまっていて9日になってしまう!

解決方法

一旦、DateからDateComponentsにしてDateに戻す関数を作成して強制的に切り捨てた

// Dateから年日月を抽出する関数
func roundDate(_ date: Date, calendar cal: Calendar) -> Date {
  return cal.date(from: DateComponents(year: cal.component(.year, from: date), month: cal.component(.month, from: date), day: cal.component(.day, from: date)))!
}

// 現在日付を取得(例えば 2017/07/12 12:01)
let today_date = Date()
// 期限を取得(例えば 2017/07/22 12:00)
let deadline_date = settings.object(forKey: "deadline_date") as? Date
// カレンダーを取得
let  calendar = Calendar(identifier: .gregorian)

// today_dateから年月日のみ抽出する -> 2017/07/12となる
let today_date_rounded =  roundDate(today_date!, calendar: calendar!)
// deadline_dateから年月日のみ抽出する -> 2017/07/22となる
let deadline_date_rounded =  roundDate(deadline_date!, calendar: calendar!)


// 現在の残り日数を計算
var deadline_days_now = calendar?.dateComponents([.day], from: today_date_rounded, to: deadline_date_rounded).day
// ->時・分が保存されてないので正しく計算されて10日になる

複数ページある場合のアプリ起動時のローカル通知の処理の設定方法

環境

つまづいたところ

LocalNotificationを実装したところ、アプリ立ち上げ中に時間になってもまったくローカル通知がなかった…

解決方法

複数ページあるiPhoneアプリの場合、ローカル通知のdelegateはAppDelegateにかく! (一つのViewControllerにuserNotificationCenterのdelegateを書いてたため、通知に音沙汰がなかったようです…)

import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {

  var window: UIWindow?
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    
    //起動中に通知を受け取るためのdelegate設定
    UNUserNotificationCenter.current().delegate = self    
    return true
  }

// いろいろ書いてあるdelegateは省略...
  
  // アプリが foreground の時に通知を受け取った時に呼ばれるメソッド
 // AppDelegateの中にuserNotificationCenterのdelegateをかく!
  func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.alert , .sound])
  }


}