20200221のJavaScriptに関する記事は19件です。

東京都内病院の緯度経度データ約200件

東京都内病院200件ほどのjsonおよびTSVのデータです。

対象病院(日本病院会リスト):
http://www.hospital.or.jp/shibu_kaiin/?sw=13&sk=1

JSONおよびtsvデータ:
https://github.com/HirotakaAseishi/tokyo_hospitalgeodata/tree/master

リストに関して、都内は病院600件のようですが、取り急ぎ病院会のリストにある200件についてwww.geocoding.jpから手作業で緯度経度をまとめてます。病院会のリストは、地理的なばらつきがあり、公立は少なくともありそうでしたので一旦これで十分だと思いここに投稿しています。

***

現在、都内でコロナウイルスの流行が顕在化している状態です。

あらゆるケースにおいて、医療機関(および医療従事者)は重要ですので、
d3.jsなどで各種データと重ねられるように取り急ぎ上記の緯度経度を調べました。

現在都内において新型コロナウイルスが流行していますが、2週間前の感染データばかりが集まっても現時点での全体像は見えませんし、頻度論の流儀で証明を待っていても遅すぎます。

各医療機関の要望に沿った検査が実行できれば、現時点に近い状態が見えてくると思います。ランダムサンプリングではありませんが、全体像を見渡すのに効率的だと思います。また、致死率の高い医療従事者や患者を守ることにもなります。

検査が出来なくても各種間接的でもっと不確かなデータの収集は様々な形で可能だと思います。

[
    {
        "id": 1,
        "type": "独立行政法人国立病院機構",
        "name": "東京医療センター",
        "url": "http://www.ntmc.go.jp/",
        "beds": 741,
        "address": "目黒区東が丘2-5-1",
        "lat": 35.626448,
        "lon": 139.666459
    },
    {
        "id": 2,
        "type": "独立行政法人国立病院機構",
        "name": "東京病院",
        "url": "http://www.hosp.go.jp/~tokyo/",
        "beds": 522,
        "address": "清瀬市竹丘3-1-1",
        "lat": 35.767834,
        "lon": 139.50523
    },
    {
        "id": 3,
        "type": "独立行政法人国立病院機構",
        "name": "村山医療センター",
        "url": "http://www.murayama-hosp.jp/",
        "beds": 303,
        "address": "武蔵村山市学園2-37-1",
        "lat": 35.747259,
        "lon": 139.399031
    },
    {
        "id": 4,
        "type": "国立大学法人",
        "name": "東京医科歯科大学医学部附属病院",
        "url": "http://www.tmd.ac.jp/medhospital/",
        "beds": 753,
        "address": "文京区湯島1-5-45",
        "lat": 35.70143,
        "lon": 139.764363
    },
    {
        "id": 5,
        "type": "国立大学法人",
        "name": "東京大学医学部附属病院",
        "url": "http://www.h.u-tokyo.ac.jp/",
        "beds": 1228,
        "address": "文京区本郷7-3-1",
        "lat": 35.714163,
        "lon": 139.762102
    },
    {
        "id": 6,
        "type": "独立行政法人労働者健康安全機構",
        "name": "東京労災病院",
        "url": "http://www.tokyoh.johas.go.jp/",
        "beds": 400,
        "address": "大田区大森南4-13-21",
        "lat": 35.565611,
        "lon": 139.747214
    },
    {
        "id": 7,
        "type": "国立研究開発法人",
        "name": "国立がん研究センター中央病院",
        "url": "http://www.ncc.go.jp/jp/ncch/",
        "beds": 578,
        "address": "中央区築地5-1-1",
        "lat": 35.665005,
        "lon": 139.767583
    },
    {
        "id": 8,
        "type": "国立研究開発法人",
        "name": "国立国際医療研究センター病院",
        "url": "http://www.ncgm.go.jp/index.html",
        "beds": 763,
        "address": "新宿区戸山1-21-1",
        "lat": 35.702292,
        "lon": 139.716664
    },
    {
        "id": 9,
        "type": "国立研究開発法人",
        "name": "国立成育医療研究センター病院",
        "url": "http://www.ncchd.go.jp/",
        "beds": 460,
        "address": "世田谷区大蔵2-10-1",
        "lat": 35.633399,
        "lon": 139.611529
    },
    {
        "id": 10,
        "type": "独立行政法人地域医療機能推進機構",
        "name": "東京蒲田医療センター",
        "url": "http://kamata.jcho.go.jp/",
        "beds": 230,
        "address": "大田区南蒲田2-19-2",
        "lat": 35.55437,
        "lon": 139.7238
    },
    {
        "id": 11,
        "type": "独立行政法人地域医療機能推進機構",
        "name": "東京城東病院",
        "url": "http://joto.jcho.go.jp/",
        "beds": 130,
        "address": "江東区亀戸9-13-1",
        "lat": 35.695177,
        "lon": 139.846095
    },
    {
        "id": 12,
        "type": "独立行政法人地域医療機能推進機構",
        "name": "東京新宿メディカルセンター",
        "url": "http://shinjuku.jcho.go.jp/",
        "beds": 520,
        "address": "新宿区津久戸町5-1",
        "lat": 35.703432,
        "lon": 139.742135
    },
    {
        "id": 13,
        "type": "独立行政法人地域医療機能推進機構",
        "name": "東京高輪病院",
        "url": "http://takanawa.jcho.go.jp/",
        "beds": 247,
        "address": "港区高輪3-10-11",
        "lat": 35.631341,
        "lon": 139.732021
    },
    {
        "id": 14,
        "type": "独立行政法人地域医療機能推進機構",
        "name": "東京山手メディカルセンター",
        "url": "http://yamate.jcho.go.jp/",
        "beds": 418,
        "address": "新宿区百人町3-22-1",
        "lat": 35.704759,
        "lon": 139.699067
    },
    {
        "id": 15,
        "type": "国(その他)",
        "name": "自衛隊中央病院",
        "url": "http://www.mod.go.jp/gsdf/chosp/",
        "beds": 500,
        "address": "世田谷区池尻1-2-24",
        "lat": 35.64481,
        "lon": 139.683125
    },
    {
        "id": 16,
        "type": "都道府県",
        "name": "東京都立大塚病院",
        "url": "http://www.byouin.metro.tokyo.jp/ohtsuka/",
        "beds": 508,
        "address": "豊島区南大塚2-8-1",
        "lat": 35.72526,
        "lon": 139.732543
    },
    {
        "id": 17,
        "type": "都道府県",
        "name": "東京都立駒込病院",
        "url": "http://www.cick.jp/",
        "beds": 815,
        "address": "文京区本駒込3-18-22",
        "lat": 35.729843,
        "lon": 139.756393
    },
    {
        "id": 18,
        "type": "都道府県",
        "name": "東京都立小児総合医療センター",
        "url": "http://www.byouin.metro.tokyo.jp/shouni/",
        "beds": 561,
        "address": "府中市武蔵台2-8-29",
        "lat": 35.691802,
        "lon": 139.462225
    },
    {
        "id": 19,
        "type": "都道府県",
        "name": "東京都立神経病院",
        "url": "http://www.byouin.metro.tokyo.jp/tmnh/",
        "beds": 304,
        "address": "府中市武蔵台2-6-1",
        "lat": 35.690557,
        "lon": 139.461285
    },
    {
        "id": 20,
        "type": "都道府県",
        "name": "東京都立多摩総合医療センター",
        "url": "http://www.fuchu-hp.fuchu.tokyo.jp/",
        "beds": 789,
        "address": "府中市武蔵台2-8-29",
        "lat": 35.691802,
        "lon": 139.462225
    },
    {
        "id": 21,
        "type": "都道府県",
        "name": "東京都立広尾病院",
        "url": "http://www.byouin.metro.tokyo.jp/hiroo/",
        "beds": 426,
        "address": "渋谷区恵比寿2-34-10",
        "lat": 35.646828,
        "lon": 139.721688
    },
    {
        "id": 22,
        "type": "都道府県",
        "name": "東京都立松沢病院",
        "url": "http://www.byouin.metro.tokyo.jp/matsuzawa/",
        "beds": 898,
        "address": "世田谷区上北沢2-1-1",
        "lat": 35.66678,
        "lon": 139.620278
    },
    {
        "id": 23,
        "type": "都道府県",
        "name": "都立墨東病院",
        "url": "http://bokutoh-hp.metro.tokyo.jp/",
        "beds": 765,
        "address": "墨田区江東橋4-23-15",
        "lat": 35.694594,
        "lon": 139.818958
    },
    {
        "id": 24,
        "type": "市町村",
        "name": "稲城市立病院",
        "url": "http://www.hospital.inagi.tokyo.jp/",
        "beds": 290,
        "address": "稲城市大丸1171",
        "lat": 35.646872,
        "lon": 139.485143
    },
    {
        "id": 25,
        "type": "市町村",
        "name": "青梅市立総合病院",
        "url": "http://www.mghp.ome.tokyo.jp/",
        "beds": 529,
        "address": "青梅市東青梅4-16-5",
        "lat": 35.782502,
        "lon": 139.28118
    },
    {
        "id": 26,
        "type": "市町村",
        "name": "公立阿伎留医療センター",
        "url": "http://www.akiru-med.jp/",
        "beds": 305,
        "address": "あきる野市引田78-1",
        "lat": 35.732189,
        "lon": 139.272619
    },
    {
        "id": 27,
        "type": "市町村",
        "name": "公立昭和病院",
        "url": "http://www.kouritu-showa.jp/",
        "beds": 518,
        "address": "小平市花小金井8-1-1",
        "lat": 35.731464,
        "lon": 139.503033
    },
    {
        "id": 28,
        "type": "市町村",
        "name": "公立福生病院",
        "url": "http://www.fussahp.jp/",
        "beds": 316,
        "address": "福生市加美平1-6-1",
        "lat": 35.746974,
        "lon": 139.326844
    },
    {
        "id": 29,
        "type": "市町村",
        "name": "町田市民病院",
        "url": "http://machida-city-hospital-tokyo.jp/",
        "beds": 447,
        "address": "町田市旭町2-15-41",
        "lat": 35.556913,
        "lon": 139.438796
    },
    {
        "id": 30,
        "type": "地方独立行政法人",
        "name": "東京都健康長寿医療センター",
        "url": "http://www.tmghig.jp/",
        "beds": 550,
        "address": "板橋区栄町35-2",
        "lat": 35.751787,
        "lon": 139.703303
    },
    {
        "id": 31,
        "type": "日赤",
        "name": "大森赤十字病院",
        "url": "http://omori.jrc.or.jp/",
        "beds": 344,
        "address": "大田区中央4-30-1",
        "lat": 35.578907,
        "lon": 139.717896
    },
    {
        "id": 32,
        "type": "日赤",
        "name": "葛飾赤十字産院",
        "url": "http://katsushika.jrc.or.jp/",
        "beds": 113,
        "address": "葛飾区立石5-11-12",
        "lat": 35.742572,
        "lon": 139.846624
    },
    {
        "id": 33,
        "type": "日赤",
        "name": "日本赤十字社医療センター",
        "url": "http://www.med.jrc.or.jp/",
        "beds": 708,
        "address": "渋谷区広尾4-1-22",
        "lat": 35.654524,
        "lon": 139.717985
    },
    {
        "id": 34,
        "type": "日赤",
        "name": "武蔵野赤十字病院",
        "url": "http://www.musashino.jrc.or.jp/",
        "beds": 611,
        "address": "武蔵野市境南町1-26-1",
        "lat": 35.697696,
        "lon": 139.547536
    },
    {
        "id": 35,
        "type": "済生会",
        "name": "東京都済生会中央病院",
        "url": "http://www.saichu.jp/",
        "beds": 535,
        "address": "港区三田1-4-17",
        "lat": 35.654062,
        "lon": 139.74357
    },
    {
        "id": 36,
        "type": "済生会",
        "name": "東京都済生会向島病院",
        "url": "http://www.saiseikai-mkj.jp/",
        "beds": 102,
        "address": "墨田区八広1-5-10",
        "lat": 35.720687,
        "lon": 139.822228
    },
    {
        "id": 37,
        "type": "共済組合及び連合会",
        "name": "関東中央病院",
        "url": "http://www.kanto-ctr-hsp.com/",
        "beds": 403,
        "address": "世田谷区上用賀6-25-1",
        "lat": 35.636835,
        "lon": 139.626088
    },
    {
        "id": 38,
        "type": "共済組合及び連合会",
        "name": "九段坂病院",
        "url": "http://www.kudanzaka.com/",
        "beds": 231,
        "address": "千代田区九段南1-6-12",
        "lat": 35.693798,
        "lon": 139.752063
    },
    {
        "id": 39,
        "type": "共済組合及び連合会",
        "name": "立川病院",
        "url": "http://www.tachikawa-hosp.gr.jp/",
        "beds": 493,
        "address": "立川市錦町4-2-22",
        "lat": 35.69256,
        "lon": 139.422365
    },
    {
        "id": 40,
        "type": "共済組合及び連合会",
        "name": "東京共済病院",
        "url": "http://www.tkh.meguro.tokyo.jp/",
        "beds": 350,
        "address": "目黒区中目黒2-3-8",
        "lat": 35.641571,
        "lon": 139.704112
    },
    {
        "id": 41,
        "type": "共済組合及び連合会",
        "name": "虎の門病院",
        "url": "http://www.toranomon.gr.jp/",
        "beds": 868,
        "address": "港区虎ノ門2-2-2",
        "lat": 35.669009,
        "lon": 139.746173
    },
    {
        "id": 42,
        "type": "共済組合及び連合会",
        "name": "三宿病院",
        "url": "http://www.mishuku.gr.jp/",
        "beds": 253,
        "address": "目黒区上目黒5-33-12",
        "lat": 35.642356,
        "lon": 139.68526
    },
    {
        "id": 43,
        "type": "国民健康保険組合",
        "name": "総合病院厚生中央病院",
        "url": "http://kohseichuo.jp/",
        "beds": 320,
        "address": "目黒区三田1-11-7",
        "lat": 35.641464,
        "lon": 139.712549
    },
    {
        "id": 44,
        "type": "公益法人",
        "name": "愛誠病院",
        "url": "http://www.aisei-byouin.or.jp/",
        "beds": 441,
        "address": "板橋区加賀1-3-1",
        "lat": 35.753788,
        "lon": 139.721035
    },
    {
        "id": 45,
        "type": "公益法人",
        "name": "板橋区医師会病院",
        "url": "http://www.itabashi-med.jp/",
        "beds": 192,
        "address": "板橋区高島平3-12-6",
        "lat": 35.786955,
        "lon": 139.658041
    },
    {
        "id": 46,
        "type": "公益法人",
        "name": "永寿総合病院",
        "url": "http://www.eijuhp.com/index.html",
        "beds": 400,
        "address": "台東区東上野2-23-16",
        "lat": 35.7097,
        "lon": 139.779703
    },
    {
        "id": 47,
        "type": "公益法人",
        "name": "永寿総合病院 柳橋分院",
        "url": "http://www.yanagibashihp.com/",
        "beds": 80,
        "address": "台東区柳橋2-20-4",
        "lat": 35.698941,
        "lon": 139.789649
    },
    {
        "id": 48,
        "type": "公益法人",
        "name": "荏原病院",
        "url": "http://www.ebara-hp.ota.tokyo.jp/",
        "beds": 506,
        "address": "大田区東雪谷4-5-10",
        "lat": 35.593755,
        "lon": 139.693208
    },
    {
        "id": 49,
        "type": "公益法人",
        "name": "大久保病院",
        "url": "http://www.ohkubohospital.jp/",
        "beds": 304,
        "address": "新宿区歌舞伎町2-44-1",
        "lat": 35.696697,
        "lon": 139.701143
    },
    {
        "id": 50,
        "type": "公益法人",
        "name": "がん研究会有明病院",
        "url": "http://www.jfcr.or.jp/hospital/",
        "beds": 700,
        "address": "江東区有明3-8-31",
        "lat": 35.634222,
        "lon": 139.794691
    },
    {
        "id": 51,
        "type": "公益法人",
        "name": "杏雲堂病院",
        "url": "http://www.kyoundo.jp/",
        "beds": 198,
        "address": "千代田区神田駿河台1-8",
        "lat": 35.698015,
        "lon": 139.763245
    },
    {
        "id": 52,
        "type": "公益法人",
        "name": "榊原記念病院",
        "url": "http://www.hospital.heart.or.jp/",
        "beds": 320,
        "address": "府中市朝日町3-16-1",
        "lat": 35.66635,
        "lon": 139.520228
    },
    {
        "id": 53,
        "type": "公益法人",
        "name": "三楽病院",
        "url": "http://www.sanraku.or.jp/",
        "beds": 270,
        "address": "千代田区神田駿河台2-5",
        "lat": 35.699416,
        "lon": 139.761351
    },
    {
        "id": 54,
        "type": "公益法人",
        "name": "心臓血管研究所付属病院",
        "url": "https://www.cvi.or.jp/",
        "beds": 74,
        "address": "港区西麻布3-2-19",
        "lat": 35.658924,
        "lon": 139.727265
    },
    {
        "id": 55,
        "type": "公益法人",
        "name": "新山手病院",
        "url": "http://www.shinyamanote.jp/",
        "beds": 180,
        "address": "東村山市諏訪町3-6-1",
        "lat": 35.770348,
        "lon": 139.462541
    },
    {
        "id": 56,
        "type": "公益法人",
        "name": "第三北品川病院",
        "url": "http://kcmi.or.jp/daisankitashinagawa/",
        "beds": 114,
        "address": "品川区北品川3-3-7",
        "lat": 35.621322,
        "lon": 139.73886
    },
    {
        "id": 57,
        "type": "公益法人",
        "name": "玉川病院",
        "url": "http://www.tamagawa-hosp.jp/",
        "beds": 389,
        "address": "世田谷区瀬田4-8-1",
        "lat": 35.620442,
        "lon": 139.624341
    },
    {
        "id": 58,
        "type": "公益法人",
        "name": "多摩南部地域病院",
        "url": "http://www.tamanan-hp.com/",
        "beds": 287,
        "address": "多摩市中沢2-1-2",
        "lat": 35.622822,
        "lon": 139.414982
    },
    {
        "id": 59,
        "type": "公益法人",
        "name": "多摩北部医療センター",
        "url": "http://www.tamahoku-hp.jp/",
        "beds": 344,
        "address": "東村山市青葉町1-7-1",
        "lat": 35.76074,
        "lon": 139.493331
    },
    {
        "id": 60,
        "type": "公益法人",
        "name": "東部地域病院",
        "url": "http://www.tobu-hp.or.jp/",
        "beds": 314,
        "address": "葛飾区亀有5-14-1",
        "lat": 5.766202,
        "lon": 139.844142
    },
    {
        "id": 61,
        "type": "公益法人",
        "name": "豊島病院",
        "url": "http://www.toshima-hp.jp/",
        "beds": 470,
        "address": "板橋区栄町33-1",
        "lat": 35.752819,
        "lon": 139.701277
    },
    {
        "id": 62,
        "type": "公益法人",
        "name": "練馬総合病院",
        "url": "http://www.nerima-hosp.or.jp/",
        "beds": 224,
        "address": "練馬区旭丘1-24-1",
        "lat": 35.733526,
        "lon": 139.67714
    },
    {
        "id": 63,
        "type": "公益法人",
        "name": "複十字病院",
        "url": "http://www.fukujuji.org/",
        "beds": 334,
        "address": "清瀬市松山3-1-24",
        "lat": 35.771558,
        "lon": 139.512278
    },
    {
        "id": 64,
        "type": "医療法人",
        "name": "あきる台病院",
        "url": "http://www.akirudai-hp.or.jp/",
        "beds": 100,
        "address": "あきる野市秋川6-5-1",
        "lat": 35.729343,
        "lon": 139.291708
    },
    {
        "id": 65,
        "type": "医療法人",
        "name": "あけぼの病院",
        "url": "http://www.akebono-hospital.jp/",
        "beds": 98,
        "address": "町田市中町1-23-3",
        "lat": 35.549597,
        "lon": 139.445112
    },
    {
        "id": 66,
        "type": "医療法人",
        "name": "小豆沢病院",
        "url": "http://www.kenbun.or.jp/",
        "beds": 134,
        "address": "板橋区小豆沢1-6-8",
        "lat": 35.772988,
        "lon": 139.700755
    },
    {
        "id": 67,
        "type": "医療法人",
        "name": "池上総合病院",
        "url": "http://www.ikegamihosp.jp/",
        "beds": 384,
        "address": "大田区池上6-1-19",
        "lat": 35.572714,
        "lon": 139.704387
    },
    {
        "id": 68,
        "type": "医療法人",
        "name": "池袋病院",
        "url": "http://www.ikebukuro-hp.com/",
        "beds": 96,
        "address": "豊島区東池袋3-5-4",
        "lat": 35.731029,
        "lon": 139.717187
    },
    {
        "id": 69,
        "type": "医療法人",
        "name": "石川島記念病院",
        "url": "http://ishikawajima.gr.jp/",
        "beds": 47,
        "address": "中央区佃2-5-2",
        "lat": 35.667554,
        "lon": 139.785431
    },
    {
        "id": 70,
        "type": "医療法人",
        "name": "板橋中央総合病院",
        "url": "http://www.ims-itabashi.jp/",
        "beds": 579,
        "address": "板橋区小豆沢2-12-7",
        "lat": 35.775599,
        "lon": 139.69709
    },
    {
        "id": 71,
        "type": "医療法人",
        "name": "一心病院",
        "url": "http://www.isshin.net/",
        "beds": 111,
        "address": "豊島区北大塚1-18-7",
        "lat": 35.732796,
        "lon": 139.730151
    },
    {
        "id": 72,
        "type": "医療法人",
        "name": "医療法人社団博栄会 赤羽中央総合病院",
        "url": "http://www.hakueikai.or.jp/",
        "beds": 150,
        "address": "北区赤羽南2-5-12",
        "lat": 35.773201,
        "lon": 139.723185
    },
    {
        "id": 73,
        "type": "医療法人",
        "name": "岩井整形外科内科病院",
        "url": "http://www.iwai.com/iwai-seikei/",
        "beds": 56,
        "address": "江戸川区南小岩8-17-2",
        "lat": 35.733745,
        "lon": 139.884947
    },
    {
        "id": 74,
        "type": "医療法人",
        "name": "浮間中央病院",
        "url": "http://www.hakueikai.or.jp/ukima/",
        "beds": 95,
        "address": "北区赤羽北2-21-19",
        "lat": 35.784255,
        "lon": 139.703236
    },
    {
        "id": 75,
        "type": "医療法人",
        "name": "永生病院",
        "url": "http://www.eisei.or.jp/",
        "beds": 595,
        "address": "八王子市椚田町583-15",
        "lat": 35.639563,
        "lon": 139.305
    },
    {
        "id": 76,
        "type": "医療法人",
        "name": "扇大橋病院",
        "url": "http://ougioohashi-hp.webmedipr.jp/",
        "beds": 96,
        "address": "足立区扇1-55-28",
        "lat": 35.76555,
        "lon": 139.771681
    },
    {
        "id": 77,
        "type": "医療法人",
        "name": "荻窪病院",
        "url": "https://www.ogikubo-hospital.or.jp/",
        "beds": 252,
        "address": "杉並区今川3-1-24",
        "lat": 35.715238,
        "lon": 139.607275
    },
    {
        "id": 78,
        "type": "医療法人",
        "name": "織本病院",
        "url": "http://www.orimoto.or.jp/",
        "beds": 92,
        "address": "清瀬市旭が丘1-261",
        "lat": 35.79091,
        "lon": 139.534074
    },
    {
        "id": 79,
        "type": "医療法人",
        "name": "葛西中央病院",
        "url": "http://kasai-central-hospital.or.jp/",
        "beds": 57,
        "address": "江戸川区船堀7-10-3",
        "lat": 35.67671,
        "lon": 139.868744
    },
    {
        "id": 80,
        "type": "医療法人",
        "name": "金地病院",
        "url": "http://www.kanaji.jp/",
        "beds": 38,
        "address": "北区中里1-5-6",
        "lat": 35.67671,
        "lon": 139.868744
    },
    {
        "id": 81,
        "type": "医療法人",
        "name": "要町病院",
        "url": "http://www.kanamecho-hp.jp/",
        "beds": 150,
        "address": "豊島区要町1-11-13",
        "lat": 35.733669,
        "lon": 139.699126
    },
    {
        "id": 82,
        "type": "医療法人",
        "name": "上板橋病院",
        "url": "http://www.jiseikai.or.jp/kamiitabashi.html",
        "beds": 150,
        "address": "板橋区常盤台4-36-9",
        "lat": 35.765361,
        "lon": 139.676413
    },
    {
        "id": 83,
        "type": "医療法人",
        "name": "神尾記念病院",
        "url": "http://www.kamio.org/",
        "beds": 30,
        "address": "千代田区神田淡路町2-25",
        "lat": 35.697004,
        "lon": 139.766688
    },
    {
        "id": 84,
        "type": "医療法人",
        "name": "亀有病院",
        "url": "http://www.kameari-hp.com/",
        "beds": 127,
        "address": "葛飾区亀有3-36-3",
        "lat": 35.763345,
        "lon": 139.849613
    },
    {
        "id": 85,
        "type": "医療法人",
        "name": "河北前田病院",
        "url": "http://www.maeda-jp.or.jp/",
        "beds": 117,
        "address": "杉並区本天沼1-2-1",
        "lat": 35.712694,
        "lon": 139.633064
    },
    {
        "id": 86,
        "type": "医療法人",
        "name": "嬉泉病院",
        "url": "http://www.kisen.or.jp/",
        "beds": 60,
        "address": "葛飾区東金町1-35-8",
        "lat": 35.773007,
        "lon": 139.871156
    },
    {
        "id": 87,
        "type": "医療法人",
        "name": "グレイス病院",
        "url": "http://www.mcs.or.jp/",
        "beds": 120,
        "address": "日野市大字宮248",
        "lat": 35.669998,
        "lon": 139.406451
    },
    {
        "id": 88,
        "type": "医療法人",
        "name": "敬愛病院",
        "url": "http://www.keiai-hospital.jp/",
        "beds": 54,
        "address": "板橋区向原3-10-23",
        "lat": 35.744127,
        "lon": 139.681518
    },
    {
        "id": 89,
        "type": "医療法人",
        "name": "京葉病院",
        "url": "http://www.keiyo-hp.jp/",
        "beds": 60,
        "address": "江戸川区松江2-43-12",
        "lat": 35.702681,
        "lon": 139.87572
    },
    {
        "id": 90,
        "type": "医療法人",
        "name": "糀谷病院",
        "url": "http://koujiya-hospital.jp/",
        "beds": 88,
        "address": "大田区南蒲田3-3-15",
        "lat": 35.553765,
        "lon": 139.728676
    },
    {
        "id": 91,
        "type": "医療法人",
        "name": "小林病院",
        "url": "http://www.kobayashibyoin.com/",
        "beds": 115,
        "address": "板橋区成増3-10-8",
        "lat": 35.778451,
        "lon": 139.633981
    },
    {
        "id": 92,
        "type": "医療法人",
        "name": "桜台病院",
        "url": "http://www.keiseikai-group.com/sakuradai/",
        "beds": 86,
        "address": "練馬区豊玉南1-20-15",
        "lat": 35.728608,
        "lon": 139.659167
    },
    {
        "id": 93,
        "type": "医療法人",
        "name": "山王病院",
        "url": "http://www.sannoclc.or.jp/hospital/",
        "beds": 79,
        "address": "港区赤坂8-10-16",
        "lat": 35.669683,
        "lon": 139.727256
    },
    {
        "id": 94,
        "type": "医療法人",
        "name": "下井病院",
        "url": "http://www.shimoi.or.jp/",
        "beds": 60,
        "address": "足立区綾瀬3-28-8",
        "lat": 35.765277,
        "lon": 139.828982
    },
    {
        "id": 95,
        "type": "医療法人",
        "name": "荘病院",
        "url": "http://www.suginami-reha-tokyo.jp/",
        "beds": 60,
        "address": "板橋区板橋1-41-14",
        "lat": 35.748716,
        "lon": 139.715659
    },
    {
        "id": 96,
        "type": "医療法人",
        "name": "杉並リハビリテーション病院",
        "url": "http://www.suginami-reha-tokyo.jp/",
        "beds": 101,
        "address": "杉並区西荻北2-5-5",
        "lat": 35.704325,
        "lon": 139.60221
    },
    {
        "id": 97,
        "type": "医療法人",
        "name": "スズキ病院",
        "url": "http://www.suzuki-hospi.or.jp/",
        "beds": 99,
        "address": "練馬区栄町7-1",
        "lat": 35.737031,
        "lon": 139.670766
    },
    {
        "id": 98,
        "type": "医療法人",
        "name": "誠志会病院",
        "url": "http://www.seisikai.or.jp/",
        "beds": 152,
        "address": "板橋区坂下1-40-2",
        "lat": 35.779627,
        "lon": 139.681044
    },
    {
        "id": 99,
        "type": "医療法人",
        "name": "世田谷中央病院",
        "url": "http://setagaya-hp.or.jp/",
        "beds": 131,
        "address": "世田谷区世田谷1-32-18",
        "lat": 35.641196,
        "lon": 139.65054
    },
    {
        "id": 100,
        "type": "医療法人",
        "name": "セントラル病院",
        "url": "http://www.central-hospital.or.jp/",
        "beds": 92,
        "address": "渋谷区松涛2-18-1",
        "lat": 35.658885,
        "lon": 139.689644
    },
    {
        "id": 101,
        "type": "医療法人",
        "name": "総合東京病院",
        "url": "http://www.tokyo-hospital.com/",
        "beds": 451,
        "address": "中野区江古田3-15-2",
        "lat": 35.727936,
        "lon": 139.663919
    },
    {
        "id": 102,
        "type": "医療法人",
        "name": "相武病院",
        "url": "http://www.sobu-hosp.or.jp/",
        "beds": 326,
        "address": "八王子市戸吹町323-1",
        "lat": 35.709661,
        "lon": 139.294614
    },
    {
        "id": 103,
        "type": "医療法人",
        "name": "高山整形外科病院",
        "url": "http://www.takayamaseikei.or.jp/",
        "beds": 48,
        "address": "葛飾区金町3-4-5",
        "lat": 35.766435,
        "lon": 139.871646
    },
    {
        "id": 104,
        "type": "医療法人",
        "name": "竹丘病院",
        "url": "http://www.takeoka.or.jp/",
        "beds": 164,
        "address": "清瀬市竹丘2-3-7",
        "lat": 35.765141,
        "lon": 139.508916
    },
    {
        "id": 105,
        "type": "医療法人",
        "name": "竹川病院",
        "url": "http://www.takekawa.gr.jp/",
        "beds": 151,
        "address": "板橋区桜川2-19-1",
        "lat": 35.758806,
        "lon": 139.679136
    },
    {
        "id": 106,
        "type": "医療法人",
        "name": "立川中央病院",
        "url": "http://www.tactis.or.jp/",
        "beds": 115,
        "address": "立川市柴崎町2-17-14",
        "lat": 35.695744,
        "lon": 139.407122
    },
    {
        "id": 107,
        "type": "医療法人",
        "name": "田中脳神経外科病院",
        "url": "http://www.tanaka-nrsg-hp.or.jp/",
        "beds": 58,
        "address": "練馬区関町南3-9-23",
        "lat": 35.721865,
        "lon": 139.581916
    },
    {
        "id": 108,
        "type": "医療法人",
        "name": "多摩丘陵病院",
        "url": "http://www.tamakyuryo.or.jp/hospital/",
        "beds": 316,
        "address": "町田市下小山田町1491",
        "lat": 35.604829,
        "lon": 139.421785
    },
    {
        "id": 109,
        "type": "医療法人",
        "name": "多摩リハビリテーション病院",
        "url": "http://www.wafukai.or.jp/tamarb/",
        "beds": 199,
        "address": "青梅市長渕9-1412-4",
        "lat": 35.764746,
        "lon": 139.269703
    },
    {
        "id": 110,
        "type": "医療法人",
        "name": "調布東山病院",
        "url": "http://www.touzan.or.jp/",
        "beds": 83,
        "address": "調布市小島町2-32-17",
        "lat": 35.652173,
        "lon": 139.542202
    },
    {
        "id": 111,
        "type": "医療法人",
        "name": "同愛会病院",
        "url": "http://www.douaikai.jp/",
        "beds": 149,
        "address": "江戸川区松島1-42-21",
        "lat": 35.705578,
        "lon": 139.867613
    },
    {
        "id": 112,
        "type": "医療法人",
        "name": "東京衛生アドベンチスト病院",
        "url": "http://www.tokyoeisei.com/",
        "beds": 186,
        "address": "杉並区天沼3-17-3",
        "lat": 35.708108,
        "lon": 139.619395
    },
    {
        "id": 113,
        "type": "医療法人",
        "name": "東京蒲田病院",
        "url": "http://www.hospital.or.jp/shibu_kaiin/www.t-kamata-hosp.or.jp",
        "beds": 180,
        "address": "大田区西蒲田7-10-1",
        "lat": 35.564248,
        "lon": 139.71195
    },
    {
        "id": 114,
        "type": "医療法人",
        "name": "東京天使病院",
        "url": "http://www.angelcourt.or.jp/",
        "beds": 122,
        "address": "八王子市上壱分方町50-1",
        "lat": 35.684396,
        "lon": 139.28056
    },
    {
        "id": 115,
        "type": "医療法人",
        "name": "東都文京病院",
        "url": "http://www.tohtobunkyo-hp.com/",
        "beds": 126,
        "address": "文京区湯島3-5-7",
        "lat": 35.704205,
        "lon": 139.767849
    },
    {
        "id": 116,
        "type": "医療法人",
        "name": "東立病院",
        "url": "http://www.touritsu-hosp.com/pc/index.html",
        "beds": 57,
        "address": "葛飾区立石6-38-13",
        "lat": 35.743571,
        "lon": 139.854213
    },
    {
        "id": 117,
        "type": "医療法人",
        "name": "東和病院",
        "url": "http://www.towa-hp.jp/",
        "beds": 299,
        "address": "足立区東和4-7-10",
        "lat": 35.772636,
        "lon": 139.843787
    },
    {
        "id": 118,
        "type": "医療法人",
        "name": "常盤台外科病院",
        "url": "http://tokiwadai-geka.jp/",
        "beds": 99,
        "address": "板橋区常盤台2-25-20",
        "lat": 35.76253,
        "lon": 139.690034
    },
    {
        "id": 119,
        "type": "医療法人",
        "name": "としま昭和病院",
        "url": "http://www.toshimashowa.or.jp/",
        "beds": 46,
        "address": "豊島区南長崎5-17-9",
        "lat": 35.728864,
        "lon": 139.682263
    },
    {
        "id": 120,
        "type": "医療法人",
        "name": "成増厚生病院",
        "url": "http://narimasukosei-hospital.jp/",
        "beds": 530,
        "address": "板橋区三園1-19-1",
        "lat": 35.788676,
        "lon": 139.639942
    },
    {
        "id": 121,
        "type": "医療法人",
        "name": "ニューハート・ワタナベ国際病院",
        "url": "https://newheart.jp/",
        "beds": 44,
        "address": "杉並区浜田山3-19-11",
        "lat": 35.683092,
        "lon": 139.629733
    },
    {
        "id": 122,
        "type": "医療法人",
        "name": "野村病院",
        "url": "https://www.nomura.or.jp/",
        "beds": 133,
        "address": "三鷹市下連雀8-3-6",
        "lat": 35.685147,
        "lon": 139.56805
    },
    {
        "id": 123,
        "type": "医療法人",
        "name": "八王子消化器病院",
        "url": "http://www.hachiojisyokaki.com/",
        "beds": 98,
        "address": "八王子市万町177-3",
        "lat": 35.650727,
        "lon": 139.332914
    },
    {
        "id": 124,
        "type": "医療法人",
        "name": "浜田病院",
        "url": "http://www.obatakai.or.jp/",
        "beds": 22,
        "address": "千代田区神田駿河台2-5",
        "lat": 35.699416,
        "lon": 139.761351
    },
    {
        "id": 125,
        "type": "医療法人",
        "name": "半蔵門病院",
        "url": "http://www.hanzomon.com/",
        "beds": 44,
        "address": "千代田区麹町1-10",
        "lat": 35.685123,
        "lon": 139.742368
    },
    {
        "id": 126,
        "type": "医療法人",
        "name": "聖ヶ丘病院",
        "url": "http://www.hijirigaoka.or.jp/",
        "beds": 48,
        "address": "多摩市連光寺2-69-6",
        "lat": 35.639492,
        "lon": 139.453343
    },
    {
        "id": 127,
        "type": "医療法人",
        "name": "日の出ヶ丘病院",
        "url": "http://www.hinodehp.com/",
        "beds": 170,
        "address": "西多摩郡日の出町大久野310番地",
        "lat": 35.742972,
        "lon": 139.246224
    },
    {
        "id": 128,
        "type": "医療法人",
        "name": "平塚胃腸病院",
        "url": "http://www.ichou.gr.jp/",
        "beds": 40,
        "address": "豊島区西池袋3-2-16",
        "lat": 35.728831,
        "lon": 139.706096
    },
    {
        "id": 129,
        "type": "医療法人",
        "name": "藤﨑病院",
        "url": "http://www.fujisaki-hp.com/",
        "beds": 119,
        "address": "江東区南砂1-25-11",
        "lat": 35.676565,
        "lon": 139.826747
    },
    {
        "id": 130,
        "type": "医療法人",
        "name": "富士病院",
        "url": "http://fujihospital.com/",
        "beds": 92,
        "address": "北区西ヶ原3-33-11",
        "lat": 35.745024,
        "lon": 139.738606
    },
    {
        "id": 131,
        "type": "医療法人",
        "name": "富士見病院",
        "url": "http://www.fujimi-hp.or.jp/",
        "beds": 108,
        "address": "板橋区大和町14-16",
        "lat": 35.760756,
        "lon": 139.705298
    },
    {
        "id": 132,
        "type": "医療法人",
        "name": "府中恵仁会病院",
        "url": "http://www.fuchu-keijinkai.or.jp/",
        "beds": 217,
        "address": "府中市住吉町5-21-1",
        "lat": 35.657102,
        "lon": 139.455508
    },
    {
        "id": 133,
        "type": "医療法人",
        "name": "平成立石病院",
        "url": "http://www.heisei-tateishi.net/",
        "beds": 203,
        "address": "葛飾区立石5-1-9",
        "lat": 35.742205,
        "lon": 139.842137
    },
    {
        "id": 134,
        "type": "医療法人",
        "name": "右田病院",
        "url": "http://www.migitahosp.or.jp/",
        "beds": 82,
        "address": "八王子市暁町1-48-18",
        "lat": 35.668842,
        "lon": 139.340657
    },
    {
        "id": 135,
        "type": "医療法人",
        "name": "三鷹中央病院",
        "url": "http://eiju.webmedipr.jp/",
        "beds": 122,
        "address": "三鷹市上連雀5-23-10",
        "lat": 35.694986,
        "lon": 139.552407
    },
    {
        "id": 136,
        "type": "医療法人",
        "name": "南多摩病院",
        "url": "http://www.minamitama.jp/",
        "beds": 170,
        "address": "八王子市散田町3-10-1",
        "lat": 35.655339,
        "lon": 139.312865
    },
    {
        "id": 137,
        "type": "医療法人",
        "name": "みなみ野病院",
        "url": "http://www.eisei.or.jp/minamino",
        "beds": 205,
        "address": "八王子市みなみ野5-30-3",
        "lat": 35.63102,
        "lon": 139.318712
    },
    {
        "id": 138,
        "type": "医療法人",
        "name": "武蔵野中央病院",
        "url": "http://www.musashino-chuou.com/",
        "beds": 306,
        "address": "小金井市東町1-44-26",
        "lat": 35.693836,
        "lon": 139.529988
    },
    {
        "id": 139,
        "type": "医療法人",
        "name": "武蔵野徳洲会病院",
        "url": "https://www.musatoku.com/",
        "beds": 246,
        "address": "西東京市向台町3-5-48",
        "lat": 35.717483,
        "lon": 139.53324
    },
    {
        "id": 140,
        "type": "医療法人",
        "name": "目黒病院",
        "url": "http://www.meguro-hospital.com/",
        "beds": 60,
        "address": "目黒区中央町2-12-6",
        "lat": 35.631921,
        "lon": 139.691134
    },
    {
        "id": 141,
        "type": "医療法人",
        "name": "目白病院",
        "url": "http://mejirohp.jp/",
        "beds": 100,
        "address": "新宿区下落合3-22-23",
        "lat": 35.722402,
        "lon": 139.698952
    },
    {
        "id": 142,
        "type": "医療法人",
        "name": "安田病院",
        "url": "http://www.yasudahosp.jp/",
        "beds": 46,
        "address": "板橋区成増1-13-9",
        "lat": 35.775359,
        "lon": 139.632883
    },
    {
        "id": 143,
        "type": "医療法人",
        "name": "代々木病院",
        "url": "http://www.tokyo-kinikai.com/yoyogi/",
        "beds": 150,
        "address": "渋谷区千駄ヶ谷1-30-7",
        "lat": 35.680855,
        "lon": 139.709679
    },
    {
        "id": 144,
        "type": "医療法人",
        "name": "ロイヤル病院",
        "url": "http://www.mck.or.jp/",
        "beds": 198,
        "address": "杉並区下高井戸4-6-2",
        "lat": 35.670342,
        "lon": 139.627927
    },
    {
        "id": 145,
        "type": "特定医療法人",
        "name": "北多摩病院",
        "url": "https://www.kitatamahospital.net/",
        "beds": 269,
        "address": "調布市調布ヶ丘4-1-1",
        "lat": 35.659608,
        "lon": 139.54386
    },
    {
        "id": 146,
        "type": "特定医療法人",
        "name": "武蔵野陽和会病院",
        "url": "http://www.hospital.or.jp/shibu_kaiin/?sw=13&sk=1",
        "beds": 103,
        "address": "武蔵野市緑町2-1-33",
        "lat": 35.716516,
        "lon": 139.565313
    },
    {
        "id": 147,
        "type": "社会医療法人",
        "name": "いずみ記念病院",
        "url": "http://www.izumikinen.or.jp/",
        "beds": 144,
        "address": "足立区本木1-3-7",
        "lat": 35.76099,
        "lon": 139.786346
    },
    {
        "id": 148,
        "type": "社会医療法人",
        "name": "大田病院",
        "url": "http://othp.c-pronet.jp/",
        "beds": 189,
        "address": "大田区大森東4-4-14",
        "lat": 35.569193,
        "lon": 139.737833
    },
    {
        "id": 149,
        "type": "社会医療法人",
        "name": "河北総合病院",
        "url": "http://kawakita.or.jp/",
        "beds": 331,
        "address": "杉並区阿佐谷北1-7-3",
        "lat": 35.706801,
        "lon": 139.638856
    },
    {
        "id": 150,
        "type": "社会医療法人",
        "name": "社会医療法人社団 森山医会 森山記念病院",
        "url": "http://mk.moriyamaikai.or.jp/",
        "beds": 275,
        "address": "江戸川区北葛西四丁目3番1号",
        "lat": 35.672199,
        "lon": 139.861665
    },
    {
        "id": 151,
        "type": "社会医療法人",
        "name": "第一病院",
        "url": "http://www.daiichi.or.jp/",
        "beds": 136,
        "address": "葛飾区東金町4-2-10",
        "lat": 35.772367,
        "lon": 139.876405
    },
    {
        "id": 152,
        "type": "社会医療法人",
        "name": "立川相互病院",
        "url": "http://www.t-kenseikai.jp/tachisou/",
        "beds": 287,
        "address": "立川市緑町4-1",
        "lat": 35.703575,
        "lon": 139.413365
    },
    {
        "id": 153,
        "type": "社会医療法人",
        "name": "長汐病院",
        "url": "http://www.nagashio.jp/",
        "beds": 302,
        "address": "豊島区池袋1-5-8",
        "lat": 35.735391,
        "lon": 139.713124
    },
    {
        "id": 154,
        "type": "社会医療法人",
        "name": "東大和病院",
        "url": "http://www.yamatokai.or.jp/higasiyamato/",
        "beds": 284,
        "address": "東大和市南街1-13-12",
        "lat": 35.7412,
        "lon": 139.431966
    },
    {
        "id": 155,
        "type": "社会医療法人",
        "name": "牧田総合病院",
        "url": "http://www.makita-hosp.or.jp/",
        "beds": 284,
        "address": "大田区大森北1-34-6",
        "lat": 35.586089,
        "lon": 139.727256
    },
    {
        "id": 156,
        "type": "社会医療法人",
        "name": "牧田総合病院 蒲田分院",
        "url": "http://www.makita-hosp.or.jp/kamata/",
        "beds": 120,
        "address": "大田区西蒲田4-22-1",
        "lat": 35.568822,
        "lon": 139.715384
    },
    {
        "id": 157,
        "type": "社会医療法人",
        "name": "武蔵村山病院",
        "url": "http://www.yamatokai.or.jp/musasimurayama/",
        "beds": 300,
        "address": "武蔵村山市榎1-1-5",
        "lat": 35.743826,
        "lon": 139.387676
    },
    {
        "id": 158,
        "type": "私立学校法人",
        "name": "北里大学北里研究所病院",
        "url": "http://www.kitasato-u.ac.jp/hokken-hp/",
        "beds": 329,
        "address": "港区白金5-9-1",
        "lat": 35.6448,
        "lon": 139.725733
    },
    {
        "id": 159,
        "type": "私立学校法人",
        "name": "慶應義塾大学病院",
        "url": "http://www.hosp.keio.ac.jp/",
        "beds": 960,
        "address": "新宿区信濃町35",
        "lat": 35.681433,
        "lon": 139.71916
    },
    {
        "id": 160,
        "type": "私立学校法人",
        "name": "国際医療福祉大学三田病院",
        "url": "http://mita.iuhw.ac.jp/",
        "beds": 291,
        "address": "港区三田1-4-3",
        "lat": 35.653698,
        "lon": 139.742477
    },
    {
        "id": 161,
        "type": "私立学校法人",
        "name": "順天堂大学医学部附属順天堂医院",
        "url": "http://www.juntendo.ac.jp/hospital/",
        "beds": 1032,
        "address": "文京区本郷3-1-3",
        "lat": 35.702405,
        "lon": 139.762606
    },
    {
        "id": 162,
        "type": "私立学校法人",
        "name": "順天堂大学医学部附属順天堂東京江東高齢者医療センター",
        "url": "http://www.juntendo.gmc.ac.jp/",
        "beds": 404,
        "address": "江東区新砂3-3-20",
        "lat": 35.665352,
        "lon": 139.83364
    },
    {
        "id": 163,
        "type": "私立学校法人",
        "name": "順天堂大学医学部附属練馬病院",
        "url": "https://www.juntendo.ac.jp/hospital_nerima/",
        "beds": 400,
        "address": "練馬区高野台3-1-10",
        "lat": 35.742156,
        "lon": 139.614761
    },
    {
        "id": 164,
        "type": "私立学校法人",
        "name": "昭和大学病院",
        "url": "http://www.showa-u.ac.jp/SUH/",
        "beds": 815,
        "address": "品川区旗の台1-5-8",
        "lat": 35.608364,
        "lon": 139.703623
    },
    {
        "id": 165,
        "type": "私立学校法人",
        "name": "聖路加国際病院",
        "url": "http://hospital.luke.ac.jp/",
        "beds": 520,
        "address": "中央区明石町9番1号",
        "lat": 35.667309,
        "lon": 139.777298
    },
    {
        "id": 166,
        "type": "私立学校法人",
        "name": "帝京大学医学部附属病院",
        "url": "http://www.teikyo-hospital.jp/",
        "beds": 1078,
        "address": "板橋区加賀2-11-1",
        "lat": 35.759005,
        "lon": 139.713899
    },
    {
        "id": 167,
        "type": "私立学校法人",
        "name": "東京医科大学八王子医療センター",
        "url": "http://hachioji.tokyo-med.ac.jp/",
        "beds": 610,
        "address": "八王子市館町1163",
        "lat": 35.631318,
        "lon": 139.288055
    },
    {
        "id": 168,
        "type": "私立学校法人",
        "name": "東京医科大学病院",
        "url": "http://hospinfo.tokyo-med.ac.jp/",
        "beds": 1015,
        "address": "新宿区西新宿6-7-1",
        "lat": 35.693258,
        "lon": 139.691659
    },
    {
        "id": 169,
        "type": "私立学校法人",
        "name": "東京慈恵会医科大学附属病院",
        "url": "http://www.jikei.ac.jp/hospital/honin/",
        "beds": 1075,
        "address": "港区西新橋3-19-18",
        "lat": 35.663568,
        "lon": 139.751326
    },
    {
        "id": 170,
        "type": "私立学校法人",
        "name": "東京女子医科大学病院",
        "url": "http://www.twmu.ac.jp/info-twmu/",
        "beds": 1379,
        "address": "新宿区河田町8-1",
        "lat": 35.69702,
        "lon": 139.719905
    },
    {
        "id": 171,
        "type": "私立学校法人",
        "name": "東邦大学医療センター大森病院",
        "url": "http://www.omori.med.toho-u.ac.jp/",
        "beds": 934,
        "address": "大田区大森西6-11-1",
        "lat": 35.568931,
        "lon": 139.724109
    },
    {
        "id": 172,
        "type": "私立学校法人",
        "name": "日本歯科大学附属病院",
        "url": "http://dent-hosp.ndu.ac.jp/nduhosp/",
        "beds": 42,
        "address": "千代田区富士見2-3-16",
        "lat": 35.700011,
        "lon": 139.744994
    },
    {
        "id": 173,
        "type": "私立学校法人",
        "name": "日本医科大学付属病院",
        "url": "http://www.hospital.or.jp/shibu_kaiin/?sw=13&sk=1",
        "beds": 897,
        "address": "文京区千駄木1丁目1番5号",
        "lat": 35.721143,
        "lon": 139.758969
    },
    {
        "id": 174,
        "type": "私立学校法人",
        "name": "日本大学医学部附属板橋病院",
        "url": "http://www.med.nihon-u.ac.jp/hospital/itabashi/",
        "beds": 1025,
        "address": "板橋区大谷口上町30-1",
        "lat": 35.749564,
        "lon": 139.691647
    },
    {
        "id": 175,
        "type": "私立学校法人",
        "name": "日本大学病院",
        "url": "http://www.nihon-u.ac.jp/hospital/",
        "beds": 320,
        "address": "千代田区神田駿河台1-6",
        "lat": 35.697346,
        "lon": 139.762752
    },
    {
        "id": 176,
        "type": "社会福祉法人",
        "name": "あそか病院",
        "url": "http://hp.asokakai.or.jp/",
        "beds": 254,
        "address": "江東区住吉1-18-1",
        "lat": 35.689926,
        "lon": 139.811889
    },
    {
        "id": 177,
        "type": "社会福祉法人",
        "name": "江戸川病院",
        "url": "http://www.edogawa.or.jp/",
        "beds": 418,
        "address": "江戸川区東小岩2-24-18",
        "lat": 35.728473,
        "lon": 139.893084
    },
    {
        "id": 178,
        "type": "社会福祉法人",
        "name": "江戸川病院高砂分院",
        "url": "http://www.takasago-hp.jp/t_top/takasago_top.html",
        "beds": 99,
        "address": "葛飾区西水元4-5-1",
        "lat": 35.793662,
        "lon": 139.845542
    },
    {
        "id": 179,
        "type": "社会福祉法人",
        "name": "江戸川メディケア病院",
        "url": "http://www.hospital.or.jp/shibu_kaiin/www.katayama-hospital.com/",
        "beds": 150,
        "address": "江戸川区東松本2-14-12",
        "lat": 35.720265,
        "lon": 139.881562
    },
    {
        "id": 180,
        "type": "社会福祉法人",
        "name": "久我山病院",
        "url": "http://www.kugayama-hp.org/",
        "beds": 199,
        "address": "世田谷区北烏山2-14-20",
        "lat": 35.681475,
        "lon": 139.598969
    },
    {
        "id": 181,
        "type": "社会福祉法人",
        "name": "桜町病院",
        "url": "http://www.seiyohanekai.or.jp/sakuramachi-hp/",
        "beds": 199,
        "address": "小金井市桜町1-2-20",
        "lat": 35.70989,
        "lon": 139.511593
    },
    {
        "id": 182,
        "type": "社会福祉法人",
        "name": "心身障害児総合医療療育センター",
        "url": "http://www.ryouiku-net.com/",
        "beds": 256,
        "address": "板橋区小茂根1-1-10",
        "lat": 35.747385,
        "lon": 139.682685
    },
    {
        "id": 183,
        "type": "社会福祉法人",
        "name": "聖母病院",
        "url": "https://www.seibokai.or.jp/",
        "beds": 154,
        "address": "新宿区中落合2-5-1",
        "lat": 35.719919,
        "lon": 139.694364
    },
    {
        "id": 184,
        "type": "社会福祉法人",
        "name": "総合母子保健センター愛育病院",
        "url": "http://www.aiiku.net/",
        "beds": 160,
        "address": "港区芝浦1-16-10",
        "lat": 35.645958,
        "lon": 139.752468
    },
    {
        "id": 185,
        "type": "社会福祉法人",
        "name": "同愛記念病院",
        "url": "http://www.doai.jp/",
        "beds": 403,
        "address": "墨田区横網2-1-11",
        "lat": 35.699569,
        "lon": 139.794168
    },
    {
        "id": 186,
        "type": "社会福祉法人",
        "name": "東京白十字病院",
        "url": "http://www.t-hakujuji.or.jp/",
        "beds": 125,
        "address": "東村山市諏訪町2-26-1",
        "lat": 35.770984,
        "lon": 139.463579
    },
    {
        "id": 187,
        "type": "社会福祉法人",
        "name": "日暮里上宮病院",
        "url": "http://www.jyogu.com/nippori/",
        "beds": 81,
        "address": "荒川区東日暮里2-29-8",
        "lat": 35.728676,
        "lon": 139.785086
    },
    {
        "id": 188,
        "type": "社会福祉法人",
        "name": "三井記念病院",
        "url": "http://www.mitsuihosp.or.jp/",
        "beds": 482,
        "address": "千代田区神田和泉町1",
        "lat": 35.699084,
        "lon": 139.778469
    },
    {
        "id": 189,
        "type": "社会福祉法人",
        "name": "南台病院",
        "url": "http://minamidaihp.jp/",
        "beds": 140,
        "address": "小平市小川町1-485",
        "lat": 35.728184,
        "lon": 139.440266
    },
    {
        "id": 190,
        "type": "社会福祉法人",
        "name": "有隣病院",
        "url": "http://tokyoyurin-hospital.com/",
        "beds": 251,
        "address": "世田谷区船橋2-15-38",
        "lat": 35.650992,
        "lon": 139.61914
    },
    {
        "id": 191,
        "type": "社会福祉法人",
        "name": "緑風荘病院",
        "url": "http://ryokufuusou.com/",
        "beds": 199,
        "address": "東村山市萩山町3-31-1",
        "lat": 35.74425,
        "lon": 139.46754
    },
    {
        "id": 192,
        "type": "医療生協",
        "name": "王子生協病院",
        "url": "http://oujiseikyo-hp.jp/",
        "beds": 159,
        "address": "北区豊島3-4-15",
        "lat": 35.760226,
        "lon": 139.744192
    },
    {
        "id": 193,
        "type": "医療生協",
        "name": "東京健生病院",
        "url": "http://thoken.or.jp/kensei/",
        "beds": 126,
        "address": "文京区大塚4-3-8",
        "lat": 35.724521,
        "lon": 139.736004
    },
    {
        "id": 194,
        "type": "医療生協",
        "name": "新渡戸記念中野総合病院",
        "url": "http://www.nakanosogo.or.jp/",
        "beds": 296,
        "address": "中野区中央4-59-16",
        "lat": 35.702504,
        "lon": 139.667103
    },
    {
        "id": 195,
        "type": "会社",
        "name": "いすゞ病院",
        "url": "http://isuzu-hospital.jp/",
        "beds": 20,
        "address": "品川区南大井6-21-10",
        "lat": 35.589575,
        "lon": 139.732681
    },
    {
        "id": 196,
        "type": "会社",
        "name": "NTT東日本関東病院",
        "url": "http://www.ntt-east.co.jp/kmc/",
        "beds": 594,
        "address": "品川区東五反田5-9-22",
        "lat": 35.631307,
        "lon": 139.72558
    },
    {
        "id": 197,
        "type": "会社",
        "name": "JR東京総合病院",
        "url": "http://www.jreast.co.jp/hospital/index.html/",
        "beds": 448,
        "address": "渋谷区代々木2-1-3",
        "lat": 35.685464,
        "lon": 139.700149
    },
    {
        "id": 198,
        "type": "会社",
        "name": "東急病院",
        "url": "http://www.tokyu-hospital.jp/",
        "beds": 135,
        "address": "大田区北千束3-27-2",
        "lat": 35.607532,
        "lon": 139.685963
    },
    {
        "id": 199,
        "type": "会社",
        "name": "東京逓信病院",
        "url": "http://www.hospital.japanpost.jp/tokyo/",
        "beds": 461,
        "address": "千代田区富士見2-14-23",
        "lat": 35.697582,
        "lon": 139.743255
    },
    {
        "id": 200,
        "type": "その他法人",
        "name": "赤羽リハビリテーション病院",
        "url": "http://www.akabane-rh.jp/",
        "beds": 234,
        "address": "北区赤羽西6-37-12",
        "lat": 35.770318,
        "lon": 139.706138
    },
    {
        "id": 201,
        "type": "その他法人",
        "name": "蒲田リハビリテーション病院",
        "url": "http://www.kamata-rh.net/index.php",
        "beds": 180,
        "address": "大田区大森西4-14-5",
        "lat": 35.572496,
        "lon": 139.720587
    },
    {
        "id": 202,
        "type": "その他法人",
        "name": "救世軍清瀬病院",
        "url": "http://kiyosehp.salvationarmy.or.jp/",
        "beds": 142,
        "address": "清瀬市竹丘1-17-9",
        "lat": 35.769926,
        "lon": 139.506669
    },
    {
        "id": 203,
        "type": "その他法人",
        "name": "救世軍ブース記念病院",
        "url": "http://boothhp.salvationarmy.or.jp/",
        "beds": 199,
        "address": "杉並区和田1-40-5",
        "lat": 35.690519,
        "lon": 139.66021
    },
    {
        "id": 204,
        "type": "その他法人",
        "name": "クリニカルリサーチ東京病院",
        "url": "http://www.crht.jp/",
        "beds": 50,
        "address": "新宿区原町3-87-4 NTビル3F",
        "lat": 35.69773,
        "lon": 139.723412
    },
    {
        "id": 205,
        "type": "その他法人",
        "name": "厚生荘病院",
        "url": "http://www.kouseisou.jp/",
        "beds": 243,
        "address": "多摩市和田1547",
        "lat": 35.646735,
        "lon": 139.431725
    },
    {
        "id": 206,
        "type": "その他法人",
        "name": "小金井リハビリテーション病院",
        "url": "http://www.koganei-rh.net/",
        "beds": 220,
        "address": "小金井市前原町1-3-2",
        "lat": 35.688937,
        "lon": 139.512298
    },
    {
        "id": 207,
        "type": "その他法人",
        "name": "五反田リハビリテーション病院",
        "url": "http://www.gotanda-reha.com/",
        "beds": 240,
        "address": "品川区西五反田8-8-20",
        "lat": 35.621657,
        "lon": 139.720723
    },
    {
        "id": 208,
        "type": "その他法人",
        "name": "駒沢病院",
        "url": "http://www.komazawa-hp.jp/",
        "beds": 95,
        "address": "世田谷区駒沢2-2-15",
        "lat": 35.633942,
        "lon": 139.660436
    },
    {
        "id": 209,
        "type": "その他法人",
        "name": "至誠会第二病院",
        "url": "http://www.shiseikai-daini-hosp.jp/",
        "beds": 305,
        "address": "世田谷区上祖師谷5-19-1",
        "lat": 35.656429,
        "lon": 139.591587
    },
    {
        "id": 210,
        "type": "その他法人",
        "name": "城西病院",
        "url": "http://www.johsai-hp.or.jp/",
        "beds": 99,
        "address": "杉並区上荻2-42-11",
        "lat": 35.70796,
        "lon": 139.614559
    },
    {
        "id": 211,
        "type": "その他法人",
        "name": "仁和会総合病院",
        "url": "http://www.jinwakai.jp/",
        "beds": 157,
        "address": "八王子市明神町4-8-1",
        "lat": 35.658252,
        "lon": 139.341521
    },
    {
        "id": 212,
        "type": "その他法人",
        "name": "東京警察病院",
        "url": "http://www.keisatsubyoin.or.jp/",
        "beds": 415,
        "address": "中野区中野四丁目22-1",
        "lat": 35.709121,
        "lon": 139.659359
    },
    {
        "id": 213,
        "type": "その他法人",
        "name": "東京武蔵野病院",
        "url": "http://www.tmh.or.jp/",
        "beds": 619,
        "address": "板橋区小茂根4-11-11",
        "lat": 35.747142,
        "lon": 139.674687
    },
    {
        "id": 214,
        "type": "その他法人",
        "name": "原宿リハビリテーション病院",
        "url": "http://www.harajuku-reha.com/",
        "beds": 332,
        "address": "渋谷区神宮前6-26-1",
        "lat": 35.666874,
        "lon": 139.702473
    },
    {
        "id": 215,
        "type": "その他法人",
        "name": "立正佼成会附属佼成病院",
        "url": "http://www.kosei-hp.or.jp/",
        "beds": 340,
        "address": "杉並区和田2-25-1",
        "lat": 35.690181,
        "lon": 139.655795
    }
]

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptのRandom関数の説明

JavaScriptのRandom関数について

Rancom関数とは何か?ということですが、まずはその意味について説明します。
Randomとは日本語で「でたらめな」という意味を持っています。
この意味からも想像できるように実行するたびに「乱数(=でたらめな数字)を生成する」関数がRandom関数です。

次に疑問に思うことは「どんな乱数を生成するのか?」ということになりますよね?
答えは「0から1未満の小数値」で、つまり「0〜0.999…」です。

では、実際に使い方を見ていきましょう。
「0〜100」の乱数を発生させるには以下のようにプログラムを書きます。

var random = Math.floor(Math.random() * (100 + 1));

Random関数は上記のようにMath.random()と書くことで呼び出すことができます。

この時、生成される値は「0〜0.999…」なので、
発生させたい値の範囲の最大値(今回は100)に+1したものを掛けることで、
0〜100の乱数を発生させることができます。
ただし、この時生成される乱数は小数点以下の値を持っているので、Math.floorで小数点以下を切り捨てます。

最後にn〜mの範囲の乱数を求めるための一般的なソースを紹介して終わります。

var random = Math.floor(Math.random() * (m - n + 1)) + n

Random関数の理解に役立てていただけたら幸いです。

Ramdom関数はどういった場合に使えるかというと、以下のような結果をランダムに出したいときに使えます。
https://fortune.spicomi.net/yumeno-a/
https://fortune.spicomi.net/megrez-a/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】props実践編:inputの真偽値によるクラスの切り替え

switchlast.gif

前置き

今回はSwitchボタンです!✅
(予告と違う内容ですみません)
inputの真偽値によって
クラスバインディングを行います!

前回書いた記事と違うのは
Stringを渡すだけではなく
computed関数で切り替えを行う部分です?

propsでのクラスバインディングはこちら
https://note.com/aliz/n/nc4110b1128f0

構成

まずはtemplateの構成
inputをlabelで囲うとコードが
スッキリするのでこちらを採用?

書き方①
<label><input type="text"></label>

囲わない場合は

書き方②
<label for="name"></label>
<input type="text" id="name">

Step1: まずはlabel, inputを作成

switch0.gif

◾️label
・文字列は親で指定したいのでprops
 文字列だけなのでslotでも大丈夫です!
 今回はpropsを複数使うためpropsにします。

css
labelの幅を88pxにしたい!
が、labelに指定してしまうと
inputも含んだ長さのためspanを追加します。

◾️input
・input type="checkbox"に
 指定可能な属性checkedを使用
 後でクラスバインディングを紐づけるため、
 まずはcheckedされた状態から作ります✅

・inputイベント(@input)で$emit
 $emit基礎編はこちら
 https://note.com/aliz/n/nd6e771724cd7

・チェックが付けられるとイベント実行
 基本イベントハンドラは
 まとめてあるここが参考になります!
 https://blog.capilano-fw.com/?p=2787

css
まず全体をdivで囲い
そのdivにborderをつけ
●を作るdivを追加します?
●はcheckされた時の右側の配置を書きたいので
左側の分もまとめて書いちゃいましょう!✍️

?‍?ここまでのコード
scssは他のコンポーネントに影響が出ないよう、
基本的に直下セレクタ > をつけています。

SwitchButton.vue
<template>
 <label class="input switch-button">
   <span class="label">
     {{ label }}
   </span>
   <div class="box">
     <input
     :checked="checked"
       type="checkbox"
       class="input"
       @input="$emit('switch')"
     >
     <div class="mark" />
   </div>
 </label>
</template>

<script>
export default {
 props: {
   label: {
     type: String,
     default: 'label'
   },
   checked: {
     type: Boolean,
     required: true,
   },
 },
}
</script>

<style lang="scss" scoped>
 .switch-button {
   display: flex;
   align-items: center;

   > .label {
     width: 88px;
     min-width: 88px;
     color: red;
   }

   > .box {
     position: relative;
     width: 48px;
     height: 24px;
     border: 2px solid red;
     border-radius: 26px;

     > .mark {
       position: absolute;
       top: 2px;
       left: 2px;
       width: 16px;
       height: 16px;
       background-color: red;
       border-radius: 50%;
       transition: 0.12s;
     }

     > .input {
       display: none;

       &:checked ~ .mark {
         transform: translateX(24px);
         background-color: red;
       }
     }
   }
 }
</style>

親でpropsのlabelは
直接テキストを渡しています。
:label="変数名"でももちろんOK。
$emitに関しては現時点ではスルーでOK。

index.vue
<template>
 <div class="page">
   <SwitchButton
     label="LABEL"
     :checked="checked"
   />
 </div>
</template>

<script>
import SwitchButton from '~/components/SwitchButton.vue'

export default {
 components: {
   SwitchButton,
 },
 data () {
   return {
     checked: true,
   }
 }
}
</script>

Step2: クラスバインディングを追加

propsとcomputed関数を使った
クラスバインディングをしていきます。
まずはinputによる真偽値は無視しましょう。

やりたいこと
チェックされたかどうかに関係なく
クラスの付け替えで全体の色を変える??
なのでこうなればOKです!
switch2.gif

あとでチェックされていない状態
(●が左にある状態)で
この色に変わるように変更します。

Point!
・labelにクラスバインディング
・computed関数で
 propsをswitch関数で切り替え
・親でstatusがinactiveになれば
 inactiveクラスがついてピンクになる
・inactiveクラスがついた時のcssを追加

?‍?ここまでのコード

SwitchButton.vue
<template>
 <label
   :class="classes"
   class="input switch-button"
 >
   <span class="label">
     {{ label }}
   </span>
   <div class="box">
     <input
       :checked="checked"
       type="checkbox"
       class="input"
       @input="$emit('switch')"
     >
     <div class="mark" />
   </div>
 </label>
</template>

<script>
export default {
props: {
  status: {
    type: String,
    default: '',
    required: false,
    validator (value) {
      return [
        '',
        'inactive',
      ].includes(value)
    },
  },
  label: {
    type: String,
    default: 'label'
  },
  checked: {
    type: Boolean,
    required: true,
  },
},
computed: {
  classes() {
    switch (this.status) {
      case '':
       return ''
     case 'inactive':
       return 'inactive'
     default:
       return ''
    }
  },
},
}
</script>

<style lang="scss" scoped>
.switch-button {
 display: flex;
 align-items: center;

 > .label {
   width: 69px;
   min-width: 69px;
   color: red;
 }

 > .box {
   position: relative;
   width: 48px;
   height: 24px;
   border: 2px solid red;
   border-radius: 26px;

   > .mark {
     position: absolute;
     top: 2px;
     left: 2px;
     width: 16px;
     height: 16px;
     background-color: red;
     border-radius: 50%;
     transition: 0.12s;
   }

   > .input {
     display: none;

     &:checked ~ .mark {
       transform: translateX(24px);
       background-color: red;
     }
   }
 }

 &.inactive {
   > .label {
     color: pink;
   }

   > .box {
     border: 2px solid pink;

     > .mark {
       background-color: pink;
     }

     > .input:checked ~ .mark {
       background-color: pink;
     }
   }
 }
}
</style>
index.vue
<template>
 <div class="page">
   <SwitchButton
     :checked="checked"
     label="LABEL"
     status="inactive"
   />
 </div>
</template>

<script>
import SwitchButton from '~/components/SwitchButton.vue'

export default {
 components: {
   SwitchButton,
 },
 data () {
  return {
   checked: true,
  }
 },
}
</script>

これで準備はOK✨?

switchlast.gif

Step3: 真偽値とクラスバインディングの連携

いよいよinputによるクラス付け替えです!
子ではもう全てのpropsを
書いているのでやることはありません。

親で渡したpropsの
・Boolean
・String
これを変数で連携させましょう!

Point!
・:checked="value"で
 valueの初期値をfalseに
 最初は選択されていない状態に変更
・statusに三項演算を使うので:を忘れず追加
 valueがtrueなら'', falseなら'inactive'
@switch="value = !value"で
 switchイベント発火時にtrue, falseの切り替え

つまり初期値チェックしてない状態の時は
inactiveクラスがついて
ピンクになって●が左にある状態?
チェックをつけるとinactiveが外れて
通常クラスの赤になって●が右にある状態?

?‍?最終コード

SwitchButton.vue
<template>
 <div class="page">
   <SwitchButton
     :checked="value"
     label="LABEL"
     :status="value ? '' : 'inactive'"
     @switch="value = !value"
   />
 </div>
</template>

<script>
import SwitchButton from '~/components/SwitchButton.vue'

export default {
 components: {
   SwitchButton,
 },
 data () {
   return {
     value: false,
   }
 }
}
</script>
index.vue
<template>
 <label
   :class="classes"
   class="input switch-button"
 >
   <span class="label">
     {{ label }}
   </span>
   <div class="box">
     <input
       :checked="checked"
       type="checkbox"
       class="input"
       @input="$emit('switch')"
     >
     <div class="mark" />
   </div>
 </label>
</template>

<script>
export default {
props: {
  status: {
    type: String,
    default: '',
    required: false,
    validator (value) {
      return [
        '',
        'inactive',
      ].includes(value)
    },
  },
  label: {
    type: String,
    default: 'label'
  },
  checked: {
    type: Boolean,
    required: true,
  },
},
computed: {
  classes() {
    switch (this.status) {
      case '':
       return ''
     case 'inactive':
       return 'inactive'
     default:
       return ''
    }
  },
},
}
</script>

<style lang="scss" scoped>
.switch-button {
 display: flex;
 align-items: center;

 > .label {
   width: 69px;
   min-width: 69px;
   color: red;
 }

 > .box {
   position: relative;
   width: 48px;
   height: 24px;
   border: 2px solid red;
   border-radius: 26px;

   > .mark {
     position: absolute;
     top: 2px;
     left: 2px;
     width: 16px;
     height: 16px;
     background-color: red;
     border-radius: 50%;
     transition: 0.12s;
   }

   > .input {
     display: none;

     &:checked ~ .mark {
       transform: translateX(24px);
       background-color: red;
     }
   }
 }

 &.inactive {
   > .label {
     color: pink;
   }

   > .box {
     border: 2px solid pink;

     > .mark {
       background-color: pink;
     }

     > .input:checked ~ .mark {
       background-color: pink;
     }
   }
 }
}
</style>

次回はVuexの続きをやります!
公開予定日は2/28(金)です。

記事が公開したときにわかる様に、
note・Twitterフォローをお願いします?

https://twitter.com/aLizlab

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Nuxt.js】props実践編:switchボタンを作ろう!

switchlast.gif

前置き

今回はSwitchボタンです!✅
gifカクカクですが
実際はなめらかになります?
(予告と違う内容ですみません)
inputの真偽値によって
クラスバインディングを行います!

propsを主に使います。
前回書いた記事と違うのは
Stringを渡すだけではなく
computed関数で切り替えを行う部分です?

propsでのクラスバインディングはこちら
https://note.com/aliz/n/nc4110b1128f0

構成

まずはtemplateの構成
inputをlabelで囲うとコードが
スッキリするのでこちらを採用?

書き方①
<label><input type="text"></label>

囲わない場合は

書き方②
<label for="name"></label>
<input type="text" id="name">

Step1: まずはlabel, inputを作成

switch0.gif

◾️label
・文字列は親で指定したいのでprops
 文字列だけなのでslotでも大丈夫です!
 今回はpropsを複数使うためpropsにします。

css
labelの幅を88pxにしたい!
が、labelに指定してしまうと
inputも含んだ長さのためspanを追加します。

◾️input
・input type="checkbox"に
 指定可能な属性checkedを使用
 後でクラスバインディングを紐づけるため、
 まずはcheckedされた状態から作ります✅

・inputイベント(@input)で$emit
 $emit基礎編はこちら
 https://note.com/aliz/n/nd6e771724cd7

・チェックが付けられるとイベント実行
 基本イベントハンドラは
 まとめてあるここが参考になります!
 https://blog.capilano-fw.com/?p=2787

css
まず全体をdivで囲い
そのdivにborderをつけ
●を作るdivを追加します?
●はcheckされた時の右側の配置を書きたいので
左側の分もまとめて書いちゃいましょう!✍️

?‍?ここまでのコード
scssは他のコンポーネントに影響が出ないよう、
基本的に直下セレクタ > をつけています。

SwitchButton.vue
<template>
 <label class="input switch-button">
   <span class="label">
     {{ label }}
   </span>
   <div class="box">
     <input
       :checked="checked"
       type="checkbox"
       class="input"
       @input="$emit('switch')"
     >
     <div class="mark" />
   </div>
 </label>
</template>

<script>
export default {
 props: {
   label: {
     type: String,
     default: 'label'
   },
   checked: {
     type: Boolean,
     required: true,
   },
 },
}
</script>

<style lang="scss" scoped>
 .switch-button {
   display: flex;
   align-items: center;

   > .label {
     width: 88px;
     min-width: 88px;
     color: red;
   }

   > .box {
     position: relative;
     width: 48px;
     height: 24px;
     border: 2px solid red;
     border-radius: 26px;

     > .mark {
       position: absolute;
       top: 2px;
       left: 2px;
       width: 16px;
       height: 16px;
       background-color: red;
       border-radius: 50%;
       transition: 0.12s;
     }

     > .input {
       display: none;

       &:checked ~ .mark {
         transform: translateX(24px);
         background-color: red;
       }
     }
   }
 }
</style>

親でpropsのlabelは
直接テキストを渡しています。
:label="変数名"でももちろんOK。
$emitに関しては現時点ではスルーでOK。

index.vue
<template>
 <div class="page">
   <SwitchButton
     label="LABEL"
     :checked="checked"
   />
 </div>
</template>

<script>
import SwitchButton from '~/components/SwitchButton.vue'

export default {
 components: {
   SwitchButton,
 },
 data () {
   return {
     checked: true,
   }
 }
}
</script>

Step2: クラスバインディングを追加

propsとcomputed関数を使った
クラスバインディングをしていきます。
まずはinputによる真偽値は無視しましょう。

やりたいこと
チェックされたかどうかに関係なく
クラスの付け替えで全体の色を変える??
なのでこうなればOKです!
switch2.gif

あとでチェックされていない状態
(●が左にある状態)で
この色に変わるように変更します。

Point!
・labelにクラスバインディング
・computed関数で
 propsをswitch関数で切り替え
・親でstatusがinactiveになれば
 inactiveクラスがついてピンクになる
・inactiveクラスがついた時のcssを追加

?‍?ここまでのコード

SwitchButton.vue
<template>
 <label
   :class="classes"
   class="input switch-button"
 >
   <span class="label">
     {{ label }}
   </span>
   <div class="box">
     <input
       :checked="checked"
       type="checkbox"
       class="input"
       @input="$emit('switch')"
     >
     <div class="mark" />
   </div>
 </label>
</template>

<script>
export default {
props: {
  status: {
    type: String,
    default: '',
    required: false,
    validator (value) {
      return [
        '',
        'inactive',
      ].includes(value)
    },
  },
  label: {
    type: String,
    default: 'label'
  },
  checked: {
    type: Boolean,
    required: true,
  },
},
computed: {
  classes() {
    switch (this.status) {
      case '':
       return ''
     case 'inactive':
       return 'inactive'
     default:
       return ''
    }
  },
},
}
</script>

<style lang="scss" scoped>
.switch-button {
 display: flex;
 align-items: center;

 > .label {
   width: 69px;
   min-width: 69px;
   color: red;
 }

 > .box {
   position: relative;
   width: 48px;
   height: 24px;
   border: 2px solid red;
   border-radius: 26px;

   > .mark {
     position: absolute;
     top: 2px;
     left: 2px;
     width: 16px;
     height: 16px;
     background-color: red;
     border-radius: 50%;
     transition: 0.12s;
   }

   > .input {
     display: none;

     &:checked ~ .mark {
       transform: translateX(24px);
       background-color: red;
     }
   }
 }

 &.inactive {
   > .label {
     color: pink;
   }

   > .box {
     border: 2px solid pink;

     > .mark {
       background-color: pink;
     }

     > .input:checked ~ .mark {
       background-color: pink;
     }
   }
 }
}
</style>
index.vue
<template>
 <div class="page">
   <SwitchButton
     :checked="checked"
     label="LABEL"
     status="inactive"
   />
 </div>
</template>

<script>
import SwitchButton from '~/components/SwitchButton.vue'

export default {
 components: {
   SwitchButton,
 },
 data () {
  return {
   checked: true,
  }
 },
}
</script>

これで準備はOK✨?

switchlast.gif

Step3: 真偽値とクラスバインディングの連携

いよいよinputによるクラス付け替えです!
子ではもう全てのpropsを
書いているのでやることはありません。

親で渡したpropsの
・Boolean
・String
これを変数で連携させましょう!

Point!
・:checked="value"で
 valueの初期値をfalseに
 最初は選択されていない状態に変更
・statusに三項演算を使うので:を忘れず追加
 valueがtrueなら'', falseなら'inactive'
@switch="value = !value"で
 switchイベント発火時にtrue, falseの切り替え

つまり初期値チェックしてない状態の時は
inactiveクラスがついて
ピンクになって●が左にある状態?
チェックをつけるとinactiveが外れて
通常クラスの赤になって●が右にある状態?

?‍?最終コード

SwitchButton.vue
<template>
 <div class="page">
   <SwitchButton
     :checked="value"
     label="LABEL"
     :status="value ? '' : 'inactive'"
     @switch="value = !value"
   />
 </div>
</template>

<script>
import SwitchButton from '~/components/SwitchButton.vue'

export default {
 components: {
   SwitchButton,
 },
 data () {
   return {
     value: false,
   }
 }
}
</script>
index.vue
<template>
 <label
   :class="classes"
   class="input switch-button"
 >
   <span class="label">
     {{ label }}
   </span>
   <div class="box">
     <input
       :checked="checked"
       type="checkbox"
       class="input"
       @input="$emit('switch')"
     >
     <div class="mark" />
   </div>
 </label>
</template>

<script>
export default {
props: {
  status: {
    type: String,
    default: '',
    required: false,
    validator (value) {
      return [
        '',
        'inactive',
      ].includes(value)
    },
  },
  label: {
    type: String,
    default: 'label'
  },
  checked: {
    type: Boolean,
    required: true,
  },
},
computed: {
  classes() {
    switch (this.status) {
      case '':
       return ''
     case 'inactive':
       return 'inactive'
     default:
       return ''
    }
  },
},
}
</script>

<style lang="scss" scoped>
.switch-button {
 display: flex;
 align-items: center;

 > .label {
   width: 69px;
   min-width: 69px;
   color: red;
 }

 > .box {
   position: relative;
   width: 48px;
   height: 24px;
   border: 2px solid red;
   border-radius: 26px;

   > .mark {
     position: absolute;
     top: 2px;
     left: 2px;
     width: 16px;
     height: 16px;
     background-color: red;
     border-radius: 50%;
     transition: 0.12s;
   }

   > .input {
     display: none;

     &:checked ~ .mark {
       transform: translateX(24px);
       background-color: red;
     }
   }
 }

 &.inactive {
   > .label {
     color: pink;
   }

   > .box {
     border: 2px solid pink;

     > .mark {
       background-color: pink;
     }

     > .input:checked ~ .mark {
       background-color: pink;
     }
   }
 }
}
</style>

次回はVuexの続きをやります!
公開予定日は2/28(金)です。

記事が公開したときにわかる様に、
note・Twitterフォローをお願いします?

https://twitter.com/aLizlab

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

js,esファイルをtsに置き換えるのにやったこと

置き換える前の状況

  • js, es, tsファイルが混在
  • テストが書かれてないコードが存在
  • JSDocは書かれている(間違ってる箇所あり)

tsからesファイルを読み込むことは出来ないので、呼び出し先のファイルがesだと、呼び出し元ファイルもesで作らないといけない。
どこかのタイミングでesをjsに変更していればよかったのですが、ずるずるとesが増えている状況。

目的

  • 今より型安全にする
  • esファイルを駆逐する

やったこと

型定義ファイルを作成

呼び出し頻度の高いファイルにデコレーターが使われており、それに型を付けることができませんでした。
https://github.com/microsoft/TypeScript/issues/4881

仕方なく以下のように型定義ファイルを作成し、対応しました。

Xxx.d.ts
declare module "xxx/xxx/Xxx" {
    import { Test } from "test";

    export default class Xxx {
        static count() => number;
    }
}
test.ts
// 呼び出しクラスに型なくても
import Xxx from "xxx/xxx/Xxx";
// 型定義ファイルを作ったおかげて型が効く
Xxx.count();

(* as any)で対応する。

今回の目的は完全な型づけではなく、tsファイル化することだったので、
依存度が小さい(型付けで得られる効果が小さい)ファイル、かつ、型付けコストが高いものは(* as any)で対応しました。

@ts-ignoreする

(* as any)で対応できない場合や、型の解決に時間がかかる場合は@ts-ignoreで対処しました。

型がない弊害

型がないので関数のインターフェースが決めれず、以下のようなモンスターが生まれていました。

xxx.js
async function something(somethinId: number): Promise<any[] | null | object> {
  if (isHappened) {
    return [];
  }
  if (isSomething) {
    return null;
  }
  return {};
}

JSDocは書かれているものの、渡す引数の型を間違えている。(動いているの?:scream_cat:

xxx.js
export default class Test {
    /**
     * コンストラクタ
     * @param {string} name
     * @param {number} id
     */
    constructor(name, id) {
        this.name = name;
        this.id = id;
    }
}

const test = new Test(name, null);

その他にも、存在しない関数を呼び出してる等もありました。(実行されないだろう箇所に書いてあったので、問題はなかったです。)

型 >>>>>> コメント

以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScript入門Q&A(フロントエンド初心者向け)

はじめに

Java等の業務ツール系PGがフロントエンド開発を始めてみて最初に疑問に思ったところをまとめました。
調べたことを自分の中で理解しやすいように砕いているので、違う所があればご指摘下さい。
TypeScriptのこの機能はJavaのこの機能に似ている!など理解しやすくなる部分は比較して書いています。

TypeScript入門Q&A

開発前にNode.jsの導入を要求された。Node.jsってサーバーサイド開発に使うんじゃないの?

ローカルに開発環境を整えるために導入する。
Node.jsでnpmを使えるようにする→npm install -g typescriptでTypeScriptが使用可能に。
JavaScriptは基本的にブラウザエンジン上で動作しているため、ブラウザエンジンの代わりにNode.jsで実行することによりデバッグを行う。その他Web開発に必要なフレームワークや依存するファイルについてもnpm経由で導入するため、Node.jsインストール=Eclipse Marketplaceのインストールみたいなものと思っています。

何を入れれば開発が始められるの?

チェック機能付きのテキストエディタ、Node.js、TypeScriptパッケージがあれば最低限の開発は可能。
TypeScriptパッケージ導入でtscコマンドを使用して.ts→.jsへのトランスパイルが可能になるが、開発時には.tsで実行できたほうが早いためnpm install -g ts-nodeによりts-node導入がオススメ。これによりnodeコマンドから直接.tsファイルの実行が可能になります。

テキストエディターについてはTypeScriptの開発元がMicrosoftということもあり、同社から無償でリリースされているVScode一択かと思います。内部にTypeScriptのリファクタリング機能が内蔵されていたり、そもそもVSCodeの開発言語がTypeScriptなので中を見ながら勉強する事もできます(する人はいるのか・・・?)

採用事例は? 結局何に使われてるの?

TypeScriptを全面に押し出して宣伝しているものはあまり見つかりませんでした。
SPA開発に使われている多くのフレームワークは素の状態もしくはプラグインでTypeScript機能を追加できるため、SPA開発をしていたりVue・Reactを使用している中でも技術的に進んでいるチームでの採用率は高いと考えられます。

Angularでは正式採用されていることに加え、googleでは社内の標準言語になっています。
特にAngularはフルスタックフレームワークなのでバックエンド処理もTypeScriptで記入することができるため、
Spring BootとJava-Kotlinのような関係性で開発が可能です。(フルスタックなため途中採用が難しいことも同じ)

JavaScriptとの関係はどんな感じ?

AltJSと呼ばれる最終的にJavaScriptに変換される言語なので、JavaScriptの機能が包括的に使えます。
ECMAScript(JavaScriptの標準規格。バージョンみたいなやつ)で将来的に導入される予定になっている機能の中にはTypeScript側で先行実装されている物があり、tsconfigの書き換えで型付き誓約をゆるく設定しECMAScriptの新機能の恩恵を受けるために使用することもできます。

基本的にはtsc使用してトランスパイルが可能ですが、素の状態だと色々問題が出るようなのでtscでは型チェック機能をメインとして使用し、トランスパイルにはwebpackやbabelを用いる方が良いようです。

勉強の仕方がわからない!

公式ドキュメントで5分で学べるものがあったり、YYTypeScript様の開催ログで雰囲気が掴めます。
ドキュメントは詳細に読み込もうとすると学習時間のコストが高くなるのと、YYTypeScript資料については入門レベルとフロントエンドに比較的精通している人という層分けの関係上、フロントエンドを初めて学習する場合webpackやtsconfig等の知識がない状態で勉強することになり難易度が少し上がります。

自分は現在Udemyでこちらの講座を進めています。
日本語の講座は最近までありませんでしたが少しずつ増えてきてるみたいですね!Vue(またはReact)にTypeScriptプラグインを導入して進める方法も検討しましたが、TypeScriptの素の機能なのか切り分けが難しくなると判断したため、先に言語的な部分を体系的に学んでからVueに導入して学ぶ方針を選択しました。

将来性・発展性とかは実際どうなの

①バックエンド処理、フロントエンド作成の開発がTypeScriptのみでほぼ完結できること
②Microsoft開発の言語でありgoogle(Angular)、facebook(React)等規模が大きい企業が採用していること
③2017年より定期アップデートに変更され、採用に値する言語になってから3年が経過していること

上記の点から見える採用事例が少ないながらも将来性が非常に高いものだと思います。
調査によるとAltJS内の人気では圧倒的であり、フロントエンド開発とJavaScriptは今後も切り離せないと考えられるのでより需要は高まってくると思います。
javascript_flavors_company_size_heatmap.png
調査結果を見てみると人気がある言語+また使用したい言語に上がっているにも関わらず100人以上の企業での使用率はElmと比べてもあまり高くありません。人数の少ない企業はもとより、ほとんどの範囲の企業に入り込むチャンスが有るのかなと思います。

まとめ・今後調べたいこと

・npmで環境構築してVScodeでコーディング。JSの機能は現行の物+先取りして実装予定の物が使用できる。
・トランスパイルされる関係上何に使われているかはわかりにくい。→これが作れる!という説明には向かない

・処理速度はどこまで実用性あるのか?(得意分野・苦手分野など)
・VueとTypeScriptの相性が悪い(らしい)のでその検証と理解
・ベストな採用事例と構成など

とりあえず基礎の学習が終わったらNuxt.jsを使用してTypeScriptを用いたSSRの実装をしてみたいと思います。

参考記事

TypeScriptをプロダクト開発に使う上でのベストプラクティスと心得
TypeScriptを使って嬉しかったこと
TypeScriptチュートリアル① -環境構築編-
モダン JavaScript プログラミングを始めるために知っておきたい技術セット
TypeScriptを使ってreactのチュートリアルを進めると捗るかなと思った(実際捗る)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Expo Pedometer(歩数計)を使うための設定方法や不具合について

はじめに

Expoでユーザーの歩数を取得するPedometer APIを検証しているのですが、いくつか留意が必要なようなのでまとめてみます。

使用方法

機能自体は非常にシンプルで、以下の3つのみです。

  1. 使用可能かどうかのチェック
  2. 期間を指定して歩数を取得
  3. 歩数のアップデート(差分)を監視

まずはexpo-sensorsをinstall/importします。

import { Pedometer } from "expo-sensors";

1. 使用可能かどうかのチェック

const isAvailable = await Pedometer.isAvailableAsync(); // Boolean

デバイスで歩数計が使用可能かどうかを非同期でチェックします。
iOSの場合はこの時にダイアログが表示されます。

2. 期間を指定して歩数を取得

const end = new Date(); // end: 現在時間
const start = new Date();
start.setDate(end.getDate() - 1); // start: 24時間前

try {
  const { steps } = await Pedometer.getStepCountAsync(start, end);
  console.log(steps); // Number
} catch (e) {
  console.log(e);
}

Date型のstartとendを指定してその間の歩数を非同期で取得します。

3. 歩数のアップデート(差分)を監視

Pedometer.watchStepCount(({ steps }) => {
  console.log(steps); // Number
});

アプリ起動中に端末を持って歩くと、その都度差分の歩数が通知されます。
傾向としては一歩ごとではなくある程度まとまった時間でカウントされるようです。
また、アプリがBackgroundで起動中(他のアプリを起動していたり、ホーム画面に戻ったり)の場合にもカウントされつつ、Foregroundに戻った瞬間に指定したコールバック関数が呼ばれ、Backgroundの状態での歩数が通知されます。

[iOS]歩数の取得制限について

Expoの内部的な実装の話になりますが、iOSネイティブにおいて歩数を取得する際は下記のような2通りの方法があります。

  • HealthKitから取得する

  • CMPedometerを使う

HealthKitの場合はHealthStoreに永続化されたユーザーのデータを取得することができるのですが、ExpoのPedometerでは後者のCMPedometerを使用しています。
この場合、取得することができる過去の歩数データは最大7日間までになっており、Expoにおいても同様の制限があります。

Expoでは現状HealthKitを使用できないため、もしPedometer(CMPedometer)以上の機能が必要な場合はEject後、HealthKitやGoogle Fitを使ったReactNative用パッケージを導入することを検討してください。

パッケージ例(こちらは未検証)
https://github.com/terrillo/rn-apple-healthkit
https://github.com/OvalMoney/react-native-fitness

CMPedometerの7日制限に関するドキュメントはこちら
しかしこの7日という数字も怪しくて、Expoで検証したところ少なくとも私の場合は過去10日間くらい取得可能でした。
それ以前の歩数の取得はエラーにはならず{ steps: 0 }が返ります。

[iOS]権限確認ダイアログについて

iOSではisAvailableAsyncの際に権限の確認ダイアログが表示されます。
App Storeにリリースする際は、このダイアログに表示される説明文を適切に設定する必要があります。(この辺り、詳しくはこちら
app.jsonexpo.ios.infoPlist.NSMotionUsageDescriptionを追加してください。

Expo Clientでは反映されませんが、ビルドして確認するとこんな感じに説明文が表示されます。
PNGイメージ 43.png

app.json(部分)
{
  "expo": {
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "バンドル名",
      "infoPlist": {
        "NSMotionUsageDescription": "[テスト文言]歩数を取得するためにモーション情報を使用します"
      }
    }
  }
}

[Android]getStepCountAsyncが使用できない

ExpoのSDK34以降、AndroidにおいてgetStepCountAsyncが使用できない問題(というか変更)が発生しています。
Githubのissueだとこの辺り。

[expo-sensors] Pedometer unable to query steps, documentation unclear/contradictory
https://github.com/expo/expo/issues/4895

現時点では完全かつ安全に解決する方法は無いようですが、上記のissueでも提案されている通り、SDK33のexpoパッケージからPedometerをimportして無理矢理使用することが可能です。
後述するGoogle OAuth Client IDの取得に関する検証の際にはこの方法で使用しています。

package.json(部分)
"dependencies": {
  "expo": "~36.0.0",
  "expo-legacy": "npm:expo@33.0.0",

SDK33以前ではexpo-sensorsに分離されていません。
このようにSDK33のexpoを別名でインストールし、Pedometerをインポートします。

import { Pedometer } from "expo-legacy";

const end = new Date();
const start = new Date();
start.setDate(end.getDate() - 1);

try {
  const { steps } = await Pedometer.getStepCountAsync(start, end);
  console.log(steps);
} catch (e) {
  console.log(e);
}

なぜSDK34以降使用できなくなっているのか

SDK33→SDK34において、Androidでの歩数の取得方法が変更されているようです。
SDK33ではGoogle Fitness(Google Fit)からユーザーのデータを取得しています。
このGoogle Fitでの実装に何かしら問題があったのかわかりませんが、SDK34以降のバージョンではAndroidのSensorEventを使用して歩数をwatchのみしており、getStepCountAsyncは実装されていません。

ソースを比べてみたい方はこちらをどうぞ。

SDK33
https://github.com/expo/expo/blob/4311483ed8d2f12a5401dc1420e1503821681013/android/versioned-abis/expoview-abi33_0_0/src/main/java/abi33_0_0/host/exp/exponent/modules/api/PedometerModule.java

SDK36(Latest)
https://github.com/expo/expo/blob/4311483ed8d2f12a5401dc1420e1503821681013/android/versioned-abis/expoview-abi36_0_0/src/main/java/abi36_0_0/expo/modules/sensors/modules/PedometerModule.java
getStepCountAsyncGetting step count for date range is not supported on Android yet.というエラーメッセージを返すようになっています。

[Android]スタンドアロンアプリでの設定方法

上述した通りSDK33まではAndroidではGoogle Fitを使用してユーザーに紐づかれた歩数を取得しているわけですが、このデータの使用には公式ドキュメントに書かれているとおり、Android OAuth Clientとしての登録が必要になります。
ここでは、Android OAuth Clientとしての設定方法について説明します。

なお、今現在はGoogle Fitを使わない仕様になっているので、このドキュメントに今もこの説明が入っているのは誤りです。
そもそもgetStepCountAsyncが使えないので嬉しくないですが、通常この設定は必要ありません

上述した方法で無理矢理getStepCountAsyncを使う場合や、将来的(希望的観測)にPedometerがGoogle Fitを使ってちゃんと実装し直された場合のために設定を検証してみます。

1. Expo Client上で確認

先ほどの方法でSDK33からPedometerをインポートし、ドキュメントのソースをちょっと変更して画面を作ります。

App.js
import React from "react";
import { Pedometer } from "expo-legacy";
import { StyleSheet, Text, View, Button } from "react-native";

export default class App extends React.Component {
  state = {
    isPedometerAvailable: "checking",
    pastStepCount: 0,
    currentStepCount: 0
  };

  componentWillUnmount() {
    this._subscription && this._subscription.remove();
    delete this._subscription;
  }

  init = async () => {
    let isPedometerAvailable = false;
    try {
      isPedometerAvailable = await Pedometer.isAvailableAsync();
      this.setState({ isPedometerAvailable: String(isPedometerAvailable) });
    } catch ({ message }) {
      this.setState({ isPedometerAvailable: `Could not get isPedometerAvailable: ${message}` });
    }
    if (isPedometerAvailable) {
      this._subscription = Pedometer.watchStepCount(result => {
        this.setState({
          currentStepCount: result.steps
        });
      });
      const end = new Date();
      const start = new Date();
      start.setDate(end.getDate() - 1);
      try {
        const { steps } = await Pedometer.getStepCountAsync(start, end);
        this.setState({ pastStepCount: steps });
      } catch ({ message }) {
        this.setState({ pastStepCount: `Could not get stepCount: ${message}` });
      }
    }
  };

  render() {
    return (
      <View style={styles.container}>
        <Text>
          Pedometer.isAvailableAsync(): {this.state.isPedometerAvailable}
        </Text>
        <Text>
          Steps taken in the last 24 hours: {this.state.pastStepCount}
        </Text>
        <Text>Walk! And watch this go up: {this.state.currentStepCount}</Text>
        <Button title="INIT" onPress={this.init} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 15,
    alignItems: "center",
    justifyContent: "center"
  }
});

Android端末のExpo Clientで確認。このような画面になります。
android
「INIT」ボタンを押し、isAvailableAsyncが呼ばれると、
android
android
このようなGoogleの承認画面(「OAuth 同意画面」)が表示され、「Allow」ボタンで許可すると、歩数データの取得が可能になります。
android

上の画面をみて推察できる通り、Expo Clientを使っている状態だとこの時のAndroid OAuth Client登録や同意画面の設定はExpo Clientのものが使われています。
これを実際にスタンドアロンアプリとしてビルドしPlay Storeに申請する際には各自での設定が必要になります。

ちなみにこの時点で、以下のような不具合があるのがわかりました。

  • 同意画面をキャンセルした時にisAvailableAsyncのPromise(返り値)が終了しない
  • 故にキャンセルされたことが検知できず、再度isAvailableAsyncを呼んでも何も起きない
  • 端末の設定からExpoアプリの「Physical activity(ボディーセンサー)」権限を不許可にすると、同意画面の際にアプリがクラッシュする
  • watchStepCountで取得できる歩数が差分の歩数ではなく累算された値になっている

おそらくSDK34以降にGoogle Fitnessでの実装を取りやめているのはこのような不安定さからでしょう。
繰り返しになってしまいますがgetStepCountAsyncが使えず内部的な実装方法が変わっているため、上記の問題はSDK36現在では発生しません。

2. スタンドアロンアプリでビルド

不具合は一旦置いておき、スタンドアロンアプリでビルドしてみます。
app.jsonでパッケージ名を設定してください。確認なので適当でいいですが実際は独自ドメインのものを使用します。

app.json(部分)
{
  "expo": {
    "android": {
      "package": "パッケージ名"
    }
  }
}
$ expo build:android

Expo Cliの流れに沿ってビルドします。

Google Fitを使用するためのAndroid OAuth Clientの登録には、アプリの証明書に含まれるSHA-1の指紋(Fingerprint)情報が必要です。

公式ドキュメント:Get an OAuth 2.0 Client ID
https://developers.google.com/fit/android/get-api-key

Expoでのビルドの場合は証明書をお任せで作成してもらうことになるので、ビルド後にapkファイルの中から指紋を抽出するという流れになります。
apkファイルをダウンロードしたら、下記のコマンドを使用します。
JDKに含まれるkeytoolコマンドがない場合は適宜インストールしてください。

$ cd ~/Downloads
$ keytool -list -printcert -jarfile <ダウンロードしたapkファイルのパス>.apk | grep SHA1 | awk '{ print $2 }'
BB:0D:AC:74:D3:21:E1:43:67:71:9B:62:91:AF:A1:66:6E:44:5D:75

こんな感じの文字列が表示されたら、コピーしておきます。
証明書は一つのExpoプロジェクトをビルドする際に最初に作成され、その後の同アプリのビルドでは同じものが使われます。
指紋情報も同アプリで一度取得したら変更は無いはずです。

3. OAuth Clientの設定

あとは上記のドキュメントに沿って設定をすればOKです。
Get_an_OAuth_2_0_Client_ID_ _ _Google_Fit_ _ _Google_Developers.png
Fitness APIを使用するための設定の流れを自動的に案内してくれるリンクがあります。これをクリックし、
Googleプロジェクトを選択します。この時点でアプリに使用するGoogleプロジェクトが存在していない場合は新たに作成してください。
Firebaseで作成したプロジェクトもここに表示され、選択することができます。
API_を有効にする_-_Google_API_コンソール.png
認証情報ウィザード_-_Test_Project_-_Google_API_コンソール.png
「プロジェクトへの認証情報の追加」画面になったら、「Fitness API」を選択されているのを確認し、

  • 「APIを呼び出す場所」 → 「Android」
  • アクセスするデータの種類 → 「ユーザーデータ」

を選択して次に進みます。
この時点で、Googleプロジェクトに紐づかれたOAuth 同意画面が無い場合は設定が求められます。
同意画面_-_Test_Project_-_Google_API_コンソール.png
同意画面_-_Test_Project_-_Google_API_コンソール.png

App Storeに申請する際はアイコン、連絡先、ホームページURL、プライバシーポリシーURL等の情報を入力する必要があるようです。その際はこの同意画面をGoogleへ「確認のため送信」します。

同意画面の設定が終わったら(検証のみであればアプリ名くらいでよいはず。「確認のため送信」はせず「保存」だけします。)、クライアントIDの作成画面に進みます。
OAuth_クライアント_ID_の作成_-_Test_Project_-_Google_API_コンソール.png
このような画面になったら、クライアントの名前(アプリ名等)、先ほど取得した指紋の文字列、app.jsonで設定したパッケージ名を入力して「作成」します。
認証情報_–_API_とサービス_–_Test_Project_–_Google_API_Console.png
同意画面の確認申請・公開までにログインが100回までに制限されるとのことです。
認証情報_–_API_とサービス_–_Test_Project_–_Google_API_Console.png
このようにプロジェクトの認証情報にOAuth 2.0 クライアントIDが追加されたら成功です。

このクライアントIDはExpoのGoogle認証機能でも使用することになります。
Pedometer(SDK33以下)の場合はこのIDをアプリ側のソースでパラメータに使用するといったことはなく、パッケージ名で紐づかれていれば問題ありません。

4. スタンドアロンアプリで確認

端末をUSBで繋いで、ADBコマンドを使ってインストールしてみます。

$ adb install <ダウンロードしたapkファイルのパス>.apk

起動し「INIT」ボタンを押してisAvailableAsyncが呼ばれると、まずはGoogleアカウントの選択画面が表示されます。
端末の言語設定を英語にしているので英語になっていますが、あとで日本語にして確認してみます。
android
ここでexpo-pedometer-exampleとなっているのはapp.jsonexpo.nameで設定されたアプリ名(デフォルトではプロジェクトIDとイコール)です。
アプリアイコンはassetsディレクトリに入っているデフォルトのアイコンが表示されています。
android
続いて権限を承認する画面になります。ここで歩数計テストとなっているのは、「OAuth 同意画面」の設定で入力された「アプリケーション名」です。
android
続いて最終確認の画面。「Allow」をタップすると、
android
getStepCountAsyncを使用して24時間以内の歩数が取得できました。

アプリ名・アイコン・日本語設定で確認

app.jsonでアプリ名を設定(OAuth 同意画面の設定に合わせ「歩数計テスト」)し、アイコンを独自のものに変更、端末の言語設定を日本語にした状態で再度確認しました。
android
android
android
設定は問題なく反映されています。
以上でOAuth Client登録について大体把握できました。

まとめ

基本動作の他、iOSではNSMotionUsageDescriptionの設定を、AndroidではGoogle OAuth Client登録の方法を確認しました。
現状、iOS・Android共に満足に使用できるのはアプリ起動中に歩数を監視する機能のみとなっていて、それ以上の機能を求める場合には難しいようでした。
ExpoアプリのGoogle OAuth Client登録についてについては基本的に必要ありませんが、SDK33と同様の機能をAndroidで実装するにはGoogle Fitを使うしかない(と思われる)ので、Expoの今後のバージョンアップによって登録が必要になる可能性があります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【TypeScript】親クラスのコンストラクタ内で子クラスのメソッドを実行ー>何故か親クラスのメンバ変数の値が

TypeScriptでちょっとハマったのでメモ。

qiita.ts
abstract class Parent {
    protected hoge: string = "Parent";
    constructor() {
        this.foo();
    }
    public abstract foo();
    public bar() {
        console.log(this.hoge);
    }
}

class Child extends Parent {
    protected hoge: string = "Child";
    constructor() {
        super();
    }
    public foo() {
        console.log(this.hoge);
    }

}

const child: Parent = new Child(); // Parent
child.foo();// Child
child.bar();// Child

上記のコードだとC#やJavaの感覚では、
Childが3回出力されるものだと勘違いしてあせった。
想定した出力(実際、JavaやC#で似たようなことをするとこのように出力される)

Child
Child
Child

実際の出力は

Parent
Child
Child

になる

これを把握せずにこんなコードを書くと・・・

qiita.ts
abstract class Parent {
    protected hoge: string = "Parent";
    protected speech: string = "";
    constructor() {
        this.init();
    }
    public abstract init();
    public bar() {
        console.log(this.hoge);
    }
    getSpeech() {
        return this.speech;
    }
}

class Child extends Parent {
    protected hoge: string = "Child";
    constructor() {
        super();
    }
    public init() {
        this.speech = `私の名前は${this.hoge}です。`
    }
}

const child: Parent = new Child();
console.log(child.getSpeech());

出力結果

私の名前はParentです。

となってちょっと悩みました。

期待した出力

私の名前はChildです。

なぜそうなるか

TypeScriptではC#やJavaのようにクラスにメンバ変数を直接書くことができる。
が、JavaScriptではそのような書き方はできず、コンストラクタ内で定義することになる。

エラーになるコード

//JavaScript
class Hoge{
 foo="a"
}

正しいJavaScript

//JavaScript
class Hoge{
 constructor(){
  this.foo="a"
 }
}

なのでTypeScriptの以下のコードはビルドされると

//TypeScript
class Hoge{
 foo="a"
}

このようなJavaScriptを吐き出します。

//JavaScript
class Hoge {
    constructor() {
        this.foo = "a";
    }
}

つまり先程のよくわからない挙動をしていたTypeScriptは以下のようなJavaScriptになるためにC#やJavaに慣れ親しんだ人にとっては意図しない挙動になったということでした。
子クラスのメンバ変数に値が定義される前に親クラスのコンストラクタが実行されていることがわかります。

//TSCでコンパイルされたJavaScript
class Parent {
    constructor() {
        this.hoge = "Parent";
        this.speech = "";
        this.init();
    }
    bar() {
        console.log(this.hoge);
    }
    getSpeech() {
        return this.speech;
    }
}
class Child extends Parent {
    constructor() {
        super();
        this.hoge = "Child";
    }
    init() {
        this.speech = `私の名前は${this.hoge}です。`;
    }
}
const child = new Child();
console.log(child.getSpeech());
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【TypeScriptの罠】親クラスのコンストラクタ内で子クラスのメソッドを実行ー>何故か親クラスのメンバ変数の値が

TypeScriptでちょっとハマったのでメモ。

qiita.ts
abstract class Parent {
    protected hoge: string = "Parent";
    constructor() {
        this.foo();
    }
    public abstract foo();
    public bar() {
        console.log(this.hoge);
    }
}

class Child extends Parent {
    protected hoge: string = "Child";
    constructor() {
        super();
    }
    public foo() {
        console.log(this.hoge);
    }

}

const child: Parent = new Child(); // Parent
child.foo();// Child
child.bar();// Child

上記のコードだとC#やJavaの感覚では、
Childが3回出力されるものだと勘違いしてあせった。
想定した出力(実際、JavaやC#で似たようなことをするとこのように出力される)

Child
Child
Child

実際の出力は

Parent
Child
Child

になる

これを把握せずにこんなコードを書くと・・・

qiita.ts
abstract class Parent {
    protected hoge: string = "Parent";
    protected speech: string = "";
    constructor() {
        this.init();
    }
    public abstract init();
    public bar() {
        console.log(this.hoge);
    }
    getSpeech() {
        return this.speech;
    }
}

class Child extends Parent {
    protected hoge: string = "Child";
    constructor() {
        super();
    }
    public init() {
        this.speech = `私の名前は${this.hoge}です。`
    }
}

const child: Parent = new Child();
console.log(child.getSpeech());

出力結果

私の名前はParentです。

となってちょっと悩みました。

期待した出力

私の名前はChildです。

なぜそうなるか

TypeScriptではC#やJavaのようにクラスにメンバ変数を直接書くことができる。
が、JavaScriptではそのような書き方はできず、コンストラクタ内で定義することになる。

エラーになるコード

//JavaScript
class Hoge{
 foo="a"
}

正しいJavaScript

//JavaScript
class Hoge{
 constructor(){
  this.foo="a"
 }
}

なのでTypeScriptの以下のコードはビルドされると

//TypeScript
class Hoge{
 foo="a"
}

このようなJavaScriptを吐き出します。

//JavaScript
class Hoge {
    constructor() {
        this.foo = "a";
    }
}

つまり先程のよくわからない挙動をしていたTypeScriptは以下のようなJavaScriptになるためにC#やJavaに慣れ親しんだ人にとっては意図しない挙動になったということでした。
子クラスのメンバ変数に値が定義される前に親クラスのコンストラクタが実行されていることがわかります。
メンバ変数の定義がsuper()のあとに入れられてしまうという仕様のせいでした。

//TSCでコンパイルされたJavaScript
class Parent {
    constructor() {
        this.hoge = "Parent";
        this.speech = "";
        this.init();
    }
    bar() {
        console.log(this.hoge);
    }
    getSpeech() {
        return this.speech;
    }
}
class Child extends Parent {
    constructor() {
        super();//<-ここに注目
        this.hoge = "Child";///<-ここに注目
    }
    init() {
        this.speech = `私の名前は${this.hoge}です。`;
    }
}
const child = new Child();
console.log(child.getSpeech());
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TypeScriptの親クラスのコンストラクタ内で子クラスのメソッドを呼ぶと。。。何故か親クラスのメンバ変数が呼ばれる

TypeScriptでちょっとハマったのでメモ。

qiita.ts
abstract class Parent {
    protected hoge: string = "Parent";
    constructor() {
        this.foo();
    }
    public abstract foo();
    public bar() {
        console.log(this.hoge);
    }
}

class Child extends Parent {
    protected hoge: string = "Child";
    constructor() {
        super();
    }
    public foo() {
        console.log(this.hoge);
    }

}

const child: Parent = new Child(); // Parent
child.foo();// Child
child.bar();// Child

上記のコードだとC#やJavaの感覚では、
Childが3回出力されるものだと勘違いしてあせった。
想定した出力(実際、JavaやC#で似たようなことをするとこのように出力される)

Child
Child
Child

実際の出力は

Parent
Child
Child

になる

これを把握せずにこんなコードを書くと・・・

qiita.ts
abstract class Parent {
    protected hoge: string = "Parent";
    protected speech: string = "";
    constructor() {
        this.init();
    }
    public abstract init();
    public bar() {
        console.log(this.hoge);
    }
    getSpeech() {
        return this.speech;
    }
}

class Child extends Parent {
    protected hoge: string = "Child";
    constructor() {
        super();
    }
    public init() {
        this.speech = `私の名前は${this.hoge}です。`
    }
}

const child: Parent = new Child();
console.log(child.getSpeech());

出力結果

私の名前はParentです。

となってちょっと悩みました。

期待した出力

私の名前はChildです。

なぜそうなるか

TypeScriptではC#やJavaのようにクラスにメンバ変数を直接書くことができる。
が、JavaScriptではそのような書き方はできず、コンストラクタ内で定義することになる。

エラーになるコード

//JavaScript
class Hoge{
 foo="a"
}

正しいJavaScript

//JavaScript
class Hoge{
 constructor(){
  this.foo="a"
 }
}

なのでTypeScriptの以下のコードはビルドされると

//TypeScript
class Hoge{
 foo="a"
}

このようなJavaScriptを吐き出します。

//JavaScript
class Hoge {
    constructor() {
        this.foo = "a";
    }
}

つまり先程のよくわからない挙動をしていたTypeScriptは以下のようなJavaScriptになるためにC#やJavaに慣れ親しんだ人にとっては意図しない挙動になったということでした。
子クラスのメンバ変数に値が定義される前に親クラスのコンストラクタが実行されていることがわかります。

//TSCでコンパイルされたJavaScript
class Parent {
    constructor() {
        this.hoge = "Parent";
        this.speech = "";
        this.init();
    }
    bar() {
        console.log(this.hoge);
    }
    getSpeech() {
        return this.speech;
    }
}
class Child extends Parent {
    constructor() {
        super();
        this.hoge = "Child";
    }
    init() {
        this.speech = `私の名前は${this.hoge}です。`;
    }
}
const child = new Child();
console.log(child.getSpeech());
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Firebase functions とJestの組み合わせで正しく終了させる

備忘録のメモです.
以下の環境でテストを書いてたら、Jestの終了に時間がかかりメッセージが出力されてました.

  • @firebase/testing 0.16.5
  • @firebase/functions 0.4.29
  • Jset 24.9.0

以下の様なメッセージになってるため、非同期処理がうまくできてない感じだけは分かった.

Jest did not exit one second after the test run has completed.

This usually means that there are asynchronous operations that weren't stopped in > your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue.

Jestのドキュメントと、@firebase/functions のコードを読みあさって原因を見つけました.

Jsetのテストのタイムアウトはデフォルトだと5秒なのに対して、@firebase/functionshttpsCallable のタイムアウトは70秒でした。以下の様に書き直せば無事期待通り終了できる様になった :tada:

const testFuncs = firebase.initializeTestApp(config);
const functions = testFuncs.functions();
functions.useFunctionsEmulator("http://localhost:5001");

// timeoutを指定
const func = functions.httpsCallable('func', { timeout: 1000 });
const res = await func({ path: "hello" });
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

React, Redux 初心者が、Hooks 時代の React, Redux, React-Redux に触れてみて感じたこと

筆者は、 Reactも Reduxも React-Reduxも初心者で、プライベートでちょっと触っている程度のペーペーです。

React に Hooks が導入されてしばらく経ちますが、React-Reduxにも Hooks が導入されていることを最近知りました。ちょっと試して見たところ、Hooksを使うことで少しだけモヤモヤが晴れてきたので、これまで理解したことを整理したいと思います。

useState, useReducer は(規模の大きな開発には)使わない

useState, useReducer はとっつきやすくてわかりやすいです。なので、ちょっとしたプログラムでは使うと思います。便利です。YoutubeのReact Today and Tomorrow and 90% Cleaner React With Hooks で、初めてこれを知った時は、感動すら、覚えました。

ですが、今回、自分でちょっと触ってみて、複数のコンポーネントにまたがるような情報を管理する必要が出てくると面倒そうだと感じました。
また、 テストも面倒なんじゃないかなと思ったりしてます。

以下が、毎度お馴染みの、 useState を使った実装例です。

src/ComponentUseState.js
import React, { useState } from "react";

const ComponentUseState = () => {
  const [num, setNum] = useState(0);

  return (
    <div>
      <h2>Using useState</h2>
      Number: {num}
      <button onClick={() => setNum(num + 1)}>+</button>
      <button onClick={() => setNum(num - 1)}>-</button>
    </div>
  );
};

export default ComponentUseState;

シンプルに書けるのですが、足し算、引き算の処理(ロジック)が、 コンポーネントの中に含まれている状態で、ちょっとテストが面倒そうです。
また、別のコンポーネントから、 num を参照したり、変更したりするのが面倒そうです。

useReducer を使うとこんな感じになります。

src/ComponentUseReducer.js
import React, { useReducer } from 'react'

const initialState = {num: 0};

const reducer = (state, action) => {
  switch(action.type) {
    case 'decrement':
      return {...state, num: state.num - 1}
    case 'increment':
      return {...state, num: state.num + 1}
    default:
      return state;
  }
}

const ComponentUseReducer = () => {
  const [state, dispatch] = useReducer(reducer, initialState)

  const { num } = state
  return (
    <div>
      <h2>Using useReducer</h2>
      Number: {num}
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </div>
  );
};

export default ComponentUseReducer;

useState を使うより、コードが長くなってしまいますが、 useReducer を使うことによって、 足し算、引き算のロジックの部分は、reducer 関数の中に閉じ込めて、コンポーネントの ComponentUseReducer とは、分離することができます。
reducer は、純粋な JavaScript のコードなので、単体で実行することができ、テストもしやすそうです。(本来、reducer は、コンポーネントとは別ファイルに分割すべきです。ここでは、敢えて分割しておりません。)

const reducer = (state, action) => {
  switch(action.type) {
    case 'decrement':
      return {...state, num: state.num - 1};
    case 'increment':
      return {...state, num: state.num + 1};
    default:
      return state;
  }
}

例えば、以下のようにChrome のデベロッパーツールの console でも単独で実行できます。

image.png

コードの中で、初期状態を示しているのが initialState です。この状態をボタンが押されるなどのイベントによってどう変化させていくのかというロジックの部分が reducer になります。ですから、この reducer の部分と initialState をどうするかは実際の開発では自分で考えて実装しないといけないところですね。(私はこのことに気づく(理解する)のに、随分と、時間がかかりました。)

ただ、 reducer 関数の書き方には、決まり事があります。

  1. 引数は、state と action の2つ。
  2. action は、 type で、state をどう変更させるかを指定する。
  3. 戻り値は、変更後の新しい state にする。

ということで、コンポーネントとロジックを分けることができたのですが、やっぱり、 num を複数コンポーネントで共有するのはちょっと面倒そうです。

React-Redux の useSelector と useDispatch を使う。 connect は使わない。

そこで、 Redux と Hooks 時代の React-Redux です。
Redux と React-Redux を使うとこんな感じになります。

src/ComponentUseReactRedux.js
import React from "react";
import { createStore } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";

const initialState = { num: 0 };

const reducer = (state, action) => {
  switch (action.type) {
    case "decrement":
      return { ...state, num: state.num - 1 };
    case "increment":
      return { ...state, num: state.num + 1 };
    default:
      return state;
  }
};

const store = createStore(reducer, initialState);

const ComponentUseReactRedux = () => {
  return (
    <div>
      <h2>ComponentUseReactRedux</h2>
      <Provider store={store}>
        <ChildComponentUseReactRedux />
      </Provider>
    </div>
  )
}

const ChildComponentUseReactRedux = () => {
  const num = useSelector(state => state.num);
  const dispatch = useDispatch();
  return (
    <div>
      <h3>Using useSelector, useDispatch</h3>
      Number: {num}
      <button onClick={() => dispatch({ type: "increment" })}>+</button>
      <button onClick={() => dispatch({ type: "decrement" })}>-</button>
    </div>
  );
};

export default ComponentUseReactRedux;

随分と長くなってしまいました :sweat_smile:

initialStatereducer は、 useReducer を使った例 src/ComponentUseReducer.js と同じです。初期値とロジックなので、ここは変わりません。

const store = createStore(reducer, initialState);

で、情報の格納先を1つ作ります。イメージ的には、これを複数のコンポーネントから参照する感じです。これはお約束の1つです。

ComponentUseReactRedux では、 React-Redux で提供される Provider を使って、 以下のように ComponentUseReactRedux の子コンポーネントからも、 store の情報にアクセスできるようにします。これもお約束ごとです。

      <Provider store={store}>
        <ChildComponentUseReactRedux />
      </Provider>

子コンポーネントの ChildComponentUseReactRedux の中では、 useSelector を使って num の値を参照できるようにします。

  const num = useSelector(state => state.num);

ここで、登場する、 state は、 reducer 関数の引数の state と同じものです。以下のように書き換えた方がわかりやすいかも知れません。

const selector = state => {
  return state.num;
}

const num = useSelector(selector);

また、 useDispatch() を使って、 dispatch を取得します。

  const dispatch = useDispatch()

ChildComponentUseReactRedux の残りの部分は、 useReducer を使った場合と同じですね。

で、この書き方だと、複数のコンポーネントから、同じ num を参照できるのです。

試しに、 ComponentUseReactRedux の中の ChildComponentUseReactRedux を2つにしてみます。

const ComponentUseReactRedux = () => {
  return (
    <div>
      <h2>ComponentUseReactRedux</h2>
      <Provider store={store}>
        <ChildComponentUseReactRedux />
        <ChildComponentUseReactRedux />
      </Provider>
    </div>
  )
}

するとその2つの子コンポーネントの num の値は連動して変化します。

gif1.gif

まとめ

  1. useStateuseReducer は 規模の大きな開発には使わない。
  2. 初期ステータスをどう定義するか、また、 reducer によってその初期ステータスをどう変化させるか(ロジック)は自分で考えて実装しないといけない。
  3. createStore を使ってステータスの格納先を作成する。
  4. Provider を使ってコンポーネント間で、ステータスを共有。
  5. useSelector を使って、ステータスのどの値を参照するのか指定する。
  6. useDispatch を使って、 dispatch を取得する。
  7. connect は使わない。 (mapStateToProps とか mapDispatchToProps とか私には難しい...。)

まだ整理できていないこと

  • useContext を使う方法もありそうなのですが、良く調べてません。
  • redux-thunk や redux-saga などの middleware の部分をどうするのが良いのか、まだ自分の中で整理ができていません。 (useCallback が使えそうですが...)

追記

今回は、 dispatch の引数(Action)を素のまま書きましたが、この部分を関数化するのが、より正しいお作法なのかも知れません。

const increment = () => {
  return {
    type: 'increment'
  };
}
const decrement = () => {
  return {
    type: 'decrement'
  };
}

を定義して、 dispatchを使うときに、 dispatch(increment())dispatch(decrement()) のようにします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

スクリプト言語 KINX(ご紹介)

はじめに

以前こんなことを書いたのだが、やはり職人として自分の道具は自分で作るか、という誘惑に駆られ作ってみた。

まあ、無い無い言っていても探せばどこかにある(ここでは言わない)ような代物だが、自己満足してても寂しいので、解説の足跡を残しておこう。

何?

手に馴染んでいる伝統的な C 系統の Syntax を受け継いだスクリプト言語。目指すは「見た目は JavaScript頭脳(中身)は Ruby安定感は AC/DC(?)」といったところ。

今はまだライブラリや基本メソッドが揃ってないので実用はまだ先だが、言語の基本的な部分は概ね動作する程度にはなった。

見た目は JavaScript

子供ではなく立派な大人。

C 系統で成功しているスクリプト言語と言えば JavaScript。ただし、デスクトップ向けとしてはいまいち。node.js は便利だがヘヴィ過ぎるし、挙動にクセがありすぎて。

一方で、Ruby の思想は好きなのだが、あの end がやたら目につく構文に抵抗がある。普通に通常のキーワードが埋もれるのだが…。

頭脳(中身)は Ruby

そうは言っても Ruby 的思考は嫌いではない。そう、見た目だけの問題なのだ。ならば違う見た目の Ruby になれば良い。

安定感は AC/DC

ブレない所を見習っていこうぜ。

名前の由来

深くは触れられない(?)が、Red Warriors の名盤「KING'S」に遡るとだけ言っておこう。

現時点で「KINX」になったので、由来のほうを(VAN HALEN で有名な「You Really Got Me」のオリジナルである)Kinks に変えるといった「家系図捏造」的なことも視野に入れている。

サンプル

詳しい解説はシリーズ化してお届けしよう。需要があるかは、気にしない。

今すぐ詳しい仕様が知りたいぜ、という方がもしいれば... 「ここ」を参照してください。

fibonacci

fib.kx
function fib(n) {
    if (n < 3) return n;
    return fib(n-2) + fib(n-1);
}

System.println(fib($$[1].toInt()));

まず書くのはベンチマーク。見た目は JavaScript。

Ruby がかつて「スピードが目的じゃないぜ、楽しさなんだぜ?」とみんなを煽っていた懐かしいあの頃。YARV がリリースされてからのノリノリさ加減を見ると、あのスタンスはまさに「酸っぱいブドウ」だったことを目の当たりに…(いや、Ruby 好きなんですよ、見た目以外は)

早速ベンチマークしてみましょう。ついでに Ruby がライバル視している Python にも登場してもらいます。この辺りと比べておけば、だいたいの実力も推測できるというもの。ソースコードは以下の通り。Python3 は Python2 より遅いので 2 で。

fib.rb
def fib(n)
  if n < 3
    return n;
  else
    return fib(n-2) + fib(n-1);
  end
end

puts fib(ARGV[0].to_i)
fib.py
import sys

def fib(n):
    if n < 3:
        return n
    else:
        return fib(n-1) + fib(n-2)

print fib(int(sys.argv[1]))

結果

まず初めにバージョン表示。

$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86-64-linux-gnu]
$ python --version
Python 2.7.15+

そして結果。単位は「秒」time コマンドで user 時間の速い順。5回くらいやって一番速かったタイム。

言語 fib(34) fib(38) fib(39)
Ruby 0.391 2.016 3.672
Kinx 0.594 4.219 6.859
Python 0.750 5.539 9.109
9227465​ 63245986​ 102334155

Ruby 超速いな。遅い遅いはまさしく過去の話だ。むしろ速い部類に入るのではないかと思われるくらい。

Python には勝ったので、まぁこんなもん。スピードキングになろうとは思っていないので、実用的な速度であれば許容範囲としておこう。しかし、実は Kinx には native という必殺技があるのです。正直実用上どこまで役に立つのかはわからないが、可能性を感じて入れてみた。ソースコードは以下。functionnative に変えただけ。

nfib.kx
native fib(n) {
    if (n < 3) return n;
    return fib(n-2) + fib(n-1);
}

System.println(fib($$[1].toInt()));

この軽微な修正がどんな影響を与えるか、先ほどの表に追加して結果を示そう。

言語 fib(34) fib(38) fib(39)
Kinx(native) 0.063 0.453 0.734
Ruby 0.391 2.016 3.672
Kinx 0.594 4.219 6.859
Python 0.750 5.539 9.109
9227465​ 63245986​ 102334155

キタ。

既に分かっているとは思うがあえて種明かしをすると、native キーワードが付いた関数はその名の通りマシン語コードにネイティブ・コンパイルし、JIT 実行させている、ということ。そら速いよね。ただし、出力されるアセンブリコードは最適化もレジスタ割当もしておらず全く美しくないが。実用上役に立つかわからない、というのは、色々と制限があるからです。後々触れると思うが、今日は触れない。詳しくは「ここ」を参照。

その他の特徴

シリーズ化するので詳しい解説は今回はしないが、どんなことができるかだけ示しておこう。

プロトタイプベース

JavaScript らしくプロトタイプベース。ただし __proto__ みたいなのは無い。オブジェクト・プロパティに直接メソッドが括りついている。オーバーライドする場合は単に上書きする。class キーワードを用意してあり、クラスの定義ができる。こんな感じ。

class ClassName {

    var privateVar_;

    private initialize() {
        privateVar_ = 0;
        this.publicVar = 0;
    }

    /* private method */
    private method1() { /* ... */ }
    private method2() { /* ... */ }

    /* public method */
    public method3() { /* ... */ }
    public method4() { /* ... */ }

}

var obj = new ClassName();

ガベージコレクション

単純明快な Stop The World のマーク・アンド・スイープ。今のところ困ってない(困るようなほど使ってない)ので、問題無い。問題があったらその時考える。

クロージャ

関数オブジェクトはレキシカル・スコープを持ち、クロージャを実現可能。JavaScript になる(ならないけど)なら当然の動作。こんな感じ。

function newCounter() {
    var i = 0;          // a lexical variable.

    return function() { // an anonymous function.
        ++i;            // a reference to a lexical variable.
        return i;
    };
}

var c1 = newCounter();
System.println(c1()); // 1
System.println(c1()); // 2
System.println(c1()); // 3
System.println(c1()); // 4
System.println(c1()); // 5

ラムダ

無名関数オブジェクトを簡潔に表記できる。ES6 でアロー関数が導入されたが全く同じではなく、先頭に & が必要。なぜかって? Yacc でうまく書けなかったんですよ。コンフリクトが解消できず(すみません)。こんな感じ。

function calc(x, y, func) {
    return func(x, y);
}

System.println("add = " + calc(10, 2, &(a, b) => a + b));
System.println("sub = " + calc(10, 2, &(a, b) => a - b));
System.println("mul = " + calc(10, 2, &(a, b) => a * b));
System.println("div = " + calc(10, 2, &(a, b) => a / b));
// add = 12
// sub = 8
// mul = 20
// div = 5

ファイバー

実はこの機能、私は使ったことが無い。ただ Ruby にあるし、便利そうなので実装。こうすればできるかなー、という軽い気持ちで試してみたら割と動いたので。ただし、yield の際にスタックの状態を保持していないので、yield は単独の式文としてのみ有効。代入は可能。どういうことかというと、関数の引数として yield を直接埋め込むとかはできないが、a = yield 10; みたいな式文は OK。尚、この時の a は呼び出し元の引数の配列が来る。簡単なサンプルはこんな感じ。

var fiber = new Fiber(function() {
    System.println("fiber 1");
    yield;
    System.println("fiber 2");
});

System.println("main 1");
fiber.resume();
System.println("main 2");
fiber.resume();
System.println("main 3");
// main 1
// fiber 1
// main 2
// fiber 2
// main 3

スプレッド演算子

ES6 で導入された(んですよね?)スプレッド(レスト)演算子。そう、これ欲しかったんですよ。超便利。色々使い道はあるが、こんな感じ。

function sample(a1, a2, ...a3) {
    // a1 = 1
    // a2 = 2
    // a3 = [3, 4, 5]
}

sample(1, 2, 3, 4, 5);

最後に

ここまで読んでくださってありがとうございます。まあ、気が向いたら使ってみてください。まだ実用的な使い道は無いと思いますが。

コントリビュートは大歓迎です。一番簡単なコントリビュートは「★」をクリックすることです。まだ全然少ないですが、増えるとモチベーション上がるよね。★が増えるといいな。

ここ (https://github.com/Kray-G/kinx)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

typescriptでProperty 'includes' does not exist on type 'string[]'.のエラーが出た時の対処法

現象

初期設定を簡易的にしたtypescriptのファイルでincludesメソッドを呼び出した時に
Property 'includes' does not exist on type 'string[]'.
とエラーが出て怒られてしまった

解決策

tsconfig.jsonのlibの箇所に何も書かれていなかったので下記のように追記

tsconfig.json

"compilerOptions": {
  //中略
  "lib": [
    "es6",
    "dom",
    "es2017"
  ],  
}

これでコンパイルもできるようになりました。

includesってes2017からだったんですね。。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Chrome for Macでwindow.open()したのに新規ウィンドウが開かない!ってなった

ブラウザの新規タブや新規ウィンドウを開く際はwindow.open()を使用しますよね。1
新規ウィンドウで開かず苦戦したので愚t共有します。2

window.open() おさらい

新規ウィンドウを開くためには以下のように指定します。

window.open('http://example.com/', '_blank', 'width=500, height=500')

結論

ブラウザの全画面表示時と通常時で挙動に違いがある。
びっくりですよね。ずっと全画面でやっていたのでハマりました。
教えてくれた人ありがとう。。。

全画面表示時

タブで開かれる。

通常時

新規ウィンドウで開かれる。


  1. https://developer.mozilla.org/ja/docs/Web/API/Window/open 

  2. バージョン: 80.0.3987.116(Official Build) (64 ビット) 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

プログラミング学習の始め方

始めに

プログラミングを勉強して2年ぐらいたったので、
プログラミングを学ぶのによかったことを書き留める。

どこから手を付ければよいか

プログラミングの知識がないと何から学習すればよいかわからないし、
調べたところで単語の意味がピンとこないと思う。
僕がおすすめするのはHTMLとJavaScriptである。(CSSは置いておく)
よく言われがちだが、僕が思う理由はいくつかある。

1. 参考書が多い

 始めは独学になると思うので、参考書通りに始めることで環境の設定などが流れで理解できる。
 変に難しい書き方をしておらず、参考書ではコードの書き方の基礎が身につく。

2. 更新した内容が目に見えてわかりやすい

 やはり自分で書いたものが目に見えてわかるとテンションが上がる。
 何事も楽しくないと続かない。

3. お金になりやすい

 人間なので、お金が絡むと学習するモチベーションが上がる。
 実際にブログやLP作成で稼いでる人がいる。

では、どのように学習するか。

学習のポイント

大切なのは自分で考えること

なにをするにしても誰かに言われてやることはつまらないし身につかない。
自分からワクワクするように気持ちを持っていこう。

少しでも理解できてきたら

想像力を膨らます。
プログラミングを書いていてこんなことができたら楽しいなと思えるような想像をする。
想像したらなにが必要か、どうすればできそうかを考える。

例えば、一覧画面を作っているならば、絞り込みを作るにはどうすればよいか。
1. 絞り込みボタンを作る
 >HTMLを変更すればいいんだな。
2. ボタンが押されたら一覧に表示知するデータが変わる
 >ボタンが押されたときにエベントを動かすにはどうすればよいか
3. 一覧にのデータを条件で絞り込む処理はどうするか
 for分とindexOfを組み合わせればできそう

このようにしてプログラミングを楽しむことが大切

あとはTry&Errorするのみ

作っているとどうしても今の自分の知識や技術ではどうしようもないものがある。
そうしたときはとにかく調べていろいろ試してみることをおすすめする。
いろいろ試した結果できなかったら一旦諦めることも重要。
そうしていろいろ試しているうちに知識が増えていて、以前できなかったことをもう一度やってみたらできるということがある。

結局のところ

大変なのは最初の数か月。
基礎が身につくと意外と難しそうでも調べればできたりする。
できることが増えると楽しい。

終わりに

2年前のプログラミングを知らなかったころは業務でわからないことづくしでひーひーいっていたが、
業務外で参考書を読み漁って1年ぐらいたったころにはプログラミングの基礎と調べる力がついていた。
プログラミングを書くことはそんなに難しくないので、興味があったらぜひはじめてみてください!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

三項演算子を書き換えるなら

三項演算子が便利すぎて、読みづらいコードが出来てしまった時の個人的回避術になります。

同値の代入

const result = a ? a : b

コンフィグの初期設定等で使われます。

const contentType = type ? type : 'application/json'

三項演算子に同じ変数が複数回書かれているのが冗長かもしれません。
下記の論理和に纏めたパターンであれば、重複を解消できそうです。

const result = a || b

入れ子

const result = a ? b ? c : d : e

ワンライナー感覚で使われたりします。

三項演算子を入れ子にすると、大体は読み辛くなります。
基本的には1個の三項演算子で完結するように考えるのが良さそうです。

この場合、最初の三項演算子を素直にif-else文に置き換えると、チャンクで若干見通しが良くなります。

aの条件分岐をif-else文に置き換え
let result
if (a) {
  result = b ? c : d
} else {
  result = e
}

あるいはbの条件分岐を関数化するのも良いかもしれません。

bの条件分岐を関数化
const fnc = b => {
  return b ? c : d
}

const result = a ? fnc(b) : e

否定

const result1 = a ? fnc(a) : true // fnc() : return true / false

フォーム入力のバリデーション等で使われます。

const validate = tel => {
  // 電話番号の整合チェック結果に応じて true / false を返すロジック
}
const valid = tel ? validate(tel) : true 

三項演算子のfalseの返り値がtrue(否定)なので、コードを読んだ時に若干分かりづらいです。trueの返り値がfalseの場合もまた然りです。

この場合、論理和の式に変換できます。

論理和の式に変換
const result = !a || fnc(a)

あるいは、関数に押し付けたりすることができます。責務の観点で見ると、こちらの方がテストもしやすくて良いかもしれません。

関数に責務を押し付ける
const fnc = val => {
  if (!val) {
    return true
  }
  // return true or false
}

const result = fnc(a)

肥大化

const result = a ? {
  hoge: 'hoge'
} : {
  fuga: 'fuga'
}

返り値に直接、オブジェクトだったり関数を定義しており、三項演算子が肥大化しています。
機能拡張等で中のオブジェクトや関数の規模が拡大した場合、三項演算子の?:の位置が離れていき可読性が極端に下がっていく可能性があります。

予め返り値を定義して、三項演算子の記述範囲を狭めた方が良さそうです。

予め定義する
const obj1 = {
  hoge: 'hoge'
}
const obj2 = {
  fuga: 'fuga'
}
const result = a ? obj1 : obj2

三項演算子が最適な場合

const result = a ? b : c

日英の言語判定等で使われます。

const msg = isJa ? 'こんにちは' : 'Hello'

aを判定してbかcを返すシンプルな処理の場合、三項演算子が一番マッチしているので書き換える必要はないと思っています。
const宣言と条件毎の初期化が同時にできるのが三項演算子の強みですね。

if文を使って置き換える場合は下記のような書き方になるかと思います。
この場合はlet宣言になり、scope内で書き換えられる可能性が出てきます。

if文に置き換える
let result = c
if (a) {
  result = b
}

あるいはif-elseに置き換えることも可能です。
代入が同層で行っているので↑より可読性は高くなりそうです。

if-else文に置き換える
let result
if (a) {
  result = b
} else {
  result = c
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者によるプログラミング学習ログ 245日目

100日チャレンジの245日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。

すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

245日目は、

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

備忘録:Javascriptでスタイルシート(CSS)を読み取ってみる。

はじめに

思いの他「知らなかった」という声をきいた内容。
Javascriptでcssの指定ができる。よく知られた内容だが、これをもっと使いやすくするコマンドがある。

getComputedStyle()
これは、「特定の要素から、その要素に対していま現在適用されているCSSを計算&取得する」というもの。
(現在の値を参照するので、たとえスタイルシートで指定されてない値であっても取得することができる。)

Javascriptでstyle.cssの中身を読み込んで現在の状態に合わせた挙動をさせる、なんて芸当が可能になれば、ウェブデザインの幅もぐんと広がるはずだ。

getComputedStyle()の用例

getComputedStyle()はCSSの値全てを一気に取得する関数である。
つまり欲しいCSSを知るためには、getComputedStyle()からさらに「getPropertyValue()」で絞り込みをかけてやる必要があるのだ。

で、以下が用例。

html
<style>
#prototype{
    color: #f9f9f9;
    width: 200px;
    background-color: #9898fd;
    padding: 1em;
}
</style>

<div id="prototype">div00</div>

<script type="text/javascript">
// 要素を取得
var element01 = document.getElementById('prototype');

// element01にかかるCSSを取得
var styles = window.getComputedStyle(element01, '');

var iro = styles.getPropertyValue('color'); // 文字色
console.log(iro);

var mleft = styles.getPropertyValue('margin-left'); // margin-left
console.log(mleft);

</script>

で、これをコンソールで見るとこうなる。

1582209003105.jpg

指定されていないmargin-leftであっても取得できているのがお分かりだろうか。いわゆるデフォルト値というやつだ。

豆知識

色系の単位はrgb、大きさや幅、長さの単位はすべてpxに統一されている。
emやvwや%でスタイルを指定していても、返ってくるのはすべてpxなのである。

また、返り値を見ればわかると思うが、返り値は数値だけでなく、その単位まで含まれた文字列で返される。
ってことは、先ほどのmargin-leftを数値として利用したいなら、

javascript
var mleft = styles.getPropertyValue('margin-left'); // margin-left

var mleft_math = Number( mleft.replace(/px/g , '') ); // 数値化

このようにひと手間加えてやる必要があることに注意しよう。

疑似要素でのgetComputedStyle()

疑似要素にかけられたスタイルであっても取得できる。
疑似要素の場合は以下のようにしてやろう。

html
<style>
#prototype{
    color: #f9f9f9;
    width: 200px;
    background-color: #9898fd;
    padding: 1em;
}

#prototype::before{
    display: block;
    content: 'free';

}
</style>

<div id="prototype">div00</div>

<script type="text/javascript">
// 要素を取得
var element01 = document.getElementById('prototype');

// element01のbeforeにかかるCSSを取得
var styles = window.getComputedStyle(element01, '::before');

var beforeFS = styles.getPropertyValue('display');
console.log(beforeFS);
</script>

1582209662416.jpg

別ブラウザでの挙動

とまあこんな具合に便利さを強調してみたgetComputedStyle()だが、欠点もある。
IEやIE、それからIEなど、このコマンドが通用しないブラウザが存在するのである。

それぞれを研究したわけではないが、おおむね以下の通りの対応。。。らしい。

古めのIE(11以前)

javascript
var element01 = document.getElementById('prototype');

// element01のbeforeにかかるCSSを取得
var styles = element01.currentStyle;

var iro = styles.getPropertyValue('color'); // 文字色
console.log(iro);

ちなみに、筆者の場合以下のようにしたらIEでも動いた。

javascript
var element01 = document.getElementById('prototype');

// element01のbeforeにかかるCSSを取得
var styles = window.getComputedStyle(element01, ''); || element01.currentStyle;

var iro = styles.getPropertyValue('color'); // 文字色
console.log(iro);

おまけ:縦横の幅

CSSはgetComputedStyle()でとれると書いたが、要素の縦幅、横幅については例外。
というのも、要素の縦幅、横幅を取得するコマンドはgetComputedStyle()とは別に存在するのである。

.clientWidth

paddingを含む横幅

.offsetWidth

border、padding、スクロールバーを含んだ横幅

.clientHeight

paddingを含む縦幅

.offsetHeight

border、padding、スクロールバーを含む縦幅

そのへんはこちらのサイト (https://ja.javascript.info/size-and-scroll) が詳しい。

参考文献

https://amachang.hatenablog.com/entry/20070611/1181554170
https://ja.javascript.info/size-and-scroll
https://qiita.com/amamamaou/items/bb79bec002a6ff033810

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む