Upgrade to Pro — share decks privately, control downloads, hide ads and more …

MIXI TECH NOTE #08

MIXI TECH NOTE #08

MIXI ENGINEERS

October 03, 2022
Tweet

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. MIXI TECH NOTE #08
    גࣜձࣾ MIXI ༗ࢤɹஶ
    2022-09-10 ൛ גࣜձࣾ MIXI ൃߦ

    View full-size slide

  2. ·͕͖͑
    ຊॻʮMIXI TECH NOTE #08ʯ͸ɺMIXIGROUP ʹॴଐ͢Δ༗ࢤୡʹΑͬͯࣥචɾ੍࡞͞Εٕͨ
    ज़ॻͰ͢ɻ࣮ࡍͷϓϩμΫτ։ൃͷݱ৔Ͱ࢖༻͞Εٕͨज़ͷ࿩΍ɺ೔ʑͷۀ຿ͷ๣Βɺݸਓతʹௐ΂
    ͨ͜ͱͳͲɺࢥ͍ࢥ͍ʹࣥච͍ͯ͠·͢ɻͦͷͨΊɺ֤ষͦΕͧΕͰ׬͍݁ͯ͠Δ಺༰ʹͳ͍ͬͯ·
    ͢ͷͰɺ޷͖ͳষ͔Β޷͖ͳॱ൪Ͱָ͓͠Έ͍ͩ͘͞ɻ
    ·ͨɺຊॻ͸ɺMIXIGROUP ʹ͋Δٕज़త஌ݟ΍ΞΠσΞΛੵۃతʹڞ༗ɾެ։͍ͯ͘͜͠ͱͰɺ
    ੈͷதʹΑΓྑ͍αʔϏε͕ҲΕग़͢͜ͱΛئͬͯץߦ͞Ε͍ͯ·͢ɻܝࡌ͞Ε͍ͯΔ৘ใ͸ɺࣥච
    ऀࣗ਎ͷ؀ڥͰݕূࣥ͠ච͞Εͨ΋ͷͰ͢ͷͰɺ͝ࢀߟʹ͞ΕΔࡍ͸ɺࣗ͝਎ͷ੹೚Ͱ൑அ͠͝׆༻
    ͍ͩ͘͞ɻͳ͓ɺจষදݱʹ͖ͭ·ͯ͠΋ɺࣥචऀࣗ਎ͷݴ༿Ͱ఻͑ͨ͘ɺϑϥϯΫͳදݱͱͳͬͯ
    ͓Γ·͢͜ͱ͝ཧղ͍͚ͨͩΕ͹ͱࢥ͍·͢ɻ
    σΟϕϩούʔϦϨʔγϣϯζνʔϜҰಉ
    ˗ຊॻʹؔ͢Δ͓໰͍߹Θͤઌ
    ɹ https://twitter.com/mixi_engineers
    ˗ MIXIGROUP ʹ͍ͭͯ
    ɹ https://mixi.co.jp/
    ˞ MIXI ͷ໊শɺ͜Εʹؔ࿈͢Δ঎ඪٴͼϩΰ͸ɺגࣜձࣾ MIXI ͷ঎ඪٴͼొ࿥঎ඪͰ͢ɻ·ͨɺ
    ֤ࣾͷձ໊ࣾɺαʔϏεٴͼ੡඼ͷ໊শ͸ɺͦΕͧΕͷॴ༗͢Δ঎ඪ·ͨ͸ొ࿥঎ඪͰ͢ɻ
    iii

    View full-size slide

  3. ໨࣍
    ·͕͖͑ iii
    ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1
    1.1 SSR ࣌ͷ feature toggle Ͱͷ෼ذ . . . . . . . . . . . . . . . . . . . . . . . . . . 1
    1.2 Service Worker ͱ͸ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
    1.3 HTTP ϦΫΤετΛϓϩΩγ͢Δ . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
    1.4 feature toggle ؅ཧ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
    1.5 feature toggle ͷ SSR ରԠ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
    1.6 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
    ୈ 2 ষ Haskell ͷ੩తαΠτδΣωϨʔλʔ 11
    2.1 Hakyll . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
    2.2 Slick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
    2.3 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
    ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 17
    3.1 ͸͡Ίʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
    3.2 ঢ়گઃఆ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
    3.3 ࢓༷ͷ෼ੳΛ͠Α͏ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
    3.4 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
    ୈ 4 ষ Rust ͷ Axum Λ࢖ͬͨ API αʔό։ൃ 29
    4.1 ͸͡Ίʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
    4.2 ToDo ΞϓϦͷ API Λ࡞Δ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
    4.3 ͓ΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
    ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 35
    5.1 ຊষʹ͍ͭͯ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
    5.2 ࢲͨͪͷڭҭࢧԉ׆ಈʹ͍ͭͯ . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
    5.3 ໰୊ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
    5.4 ໰୊ͷ෼ղ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
    v

    View full-size slide

  4. ໨࣍
    5.5 ໨ඪઃఆͱߦಈࢦ਑ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
    5.6 ίϯςϯπاըͱ͞·͟·ͳ෼ੳ . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
    5.7 ΞΠσΞͷൃ૝ͱࢥߟ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
    5.8 ࠷ޙʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
    ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 61
    6.1 ͸͡Ίʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
    6.2 ڥքσʔλͷऔΓࠐΈ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
    6.3 GeoHash-ࢢ۠ொଜςʔϒϧ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
    6.4 ύϑΥʔϚϯεଌఆ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
    6.5 ͓ΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
    ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 81
    7.1 2022 ೥Ҏલͷྺ࢙ΛৼΓฦΔ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
    7.2 ExoPlayer ͱ Jetpack Media3 ʹ͍ͭͯ . . . . . . . . . . . . . . . . . . . . . . . 84
    7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
    7.4 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
    ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 95
    8.1 ͸͡Ίʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
    8.2 Unity Transport ͷηοτΞοϓ . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
    8.3 Unity Transport ͷ௨৴ϓϩτίϧ . . . . . . . . . . . . . . . . . . . . . . . . . . 96
    8.4 ܰྔαʔό։ൃ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
    8.5 ऴΘΓʹ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
    ஶऀ঺հ 103
    vi

    View full-size slide

  5. ୈ 1 ষ
    Service Worker Λհͨ͠ feature
    toggle ؅ཧ
    feature toggle ͱ͸ ։ൃ͢Δػೳͷಈ࡞Λ༗ޮԽ͢Δ͔ແޮԽ͢Δ͔Λ੍ޚ͢ΔͨΊͷख๏Ͱ͢ɻ
    ৄ͘͠͸ɺલճͷٕज़ॻయ 12*1Ͱॻ͍ͨ ʮUnleash Λ࢖ͬͨ feature toggle ؅ཧʯ Ͱ feature
    toggle Λ࢖͏ϝϦοτ΍͜ΕΛ׆༻͢ΔτϥϯΫϕʔε։ൃʹ͍ͭͯͷ঺հΛ͍ͯ͠·͕͢ɺຊষͰ
    ͸ɺ΋͏গ͠ൃలͯ͠ Web (Next.js) ʹ͓͚Δ SSR ࣌ͷ feature toggle ͷΫϥΠΞϯτ؅ཧʹ͍ͭ
    ͯɺ Service Worker Λ׆༻ͨ͠ख๏Λ঺հ͍ͨ͠ͱࢥ͍·͢ɻ
    1.1 SSR ࣌ͷ feature toggle Ͱͷ෼ذ
    SSR ͱ͸ Server Side Rendering ͷུͰ SPA*2 Λϖʔδ͝ͱʹαʔόͰ HTML ͱͯ͠ϨϯμϦ
    ϯάͯ͠ΫϥΠΞϯτʹฦ٫͢Δख๏Ͱ͢ɻ
    ΫϥΠΞϯτ͸αʔό͔Βड͚औͬͨϨϯμϦϯά݁ՌΛύʔεͯ͠ඳըͨ͠ޙɺΫϥΠΞϯτଆ
    ͰͷεΫϦϓτ࣮ߦΛ͠·͢ɻ
    ͜ΕΛ hydration ͱ͍͏ͷͰ͕͢ɺύϑΥʔϚϯε্ͷཧ༝͔ΒαʔόαΠυͰͷϨϯμϦϯά
    ݁ՌͱΫϥΠΞϯταΠυͰͷॳճϨϯμϦϯά݁Ռ͸ඞͣҰகͤ͞Δඞཁ͕͋Δͱ͍͏ಛ௃͕͋Γ
    ·͢ɻ
    feature toggle ʹ͓͍ͯ͸ɺϑϥάͷεςʔλεʹΑͬͯϨϯμϦϯά݁ՌΛ෼ذ͍ͤͨ͞ͷͰ৔
    ߹ʹΑͬͯ͸ SSR ͨ͠ޙͷ hydration ͰϨϯμϦϯά݁ՌͷෆҰகʹΑΔΤϥʔ͕ൃੜ͢Δ͜ͱ͕
    ͋Γ·͢ɻ
    ͨͱ͑͹ɺfeature toggle ΛΫϥΠΞϯτͰ؅ཧͨ͠৔߹
    *1 ٕज़ॻయ 12: https://techbookfest.org/product/5148888694521856?productVariantID=6546902914957312
    *2 Single Page Application
    1

    View full-size slide

  6. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.2 Service Worker ͱ͸
    Ϧετ 1.1: featureToggle.ts
    1: const getFeatureToggle = () => {
    2: const featureToggle = localStorage.getItem("featureToggle");
    3:
    4: return featureToggle === "true"
    5: }
    6:
    7: const ExampleComponent = () => {
    8: const enabled = getFeatureToggle()
    9:
    10: return (
    11: <>
    12: {enabled ? new : old}
    13: >
    14: )
    15: }
    local storage ΍ session storage ͳͲͷΫϥΠΞϯτͷετϨʔδͰ؅ཧͨ͠ feature flag
    Λݺͼग़ͯ͠ɺϨϯμϦϯά݁ՌΛ෼ذͯͦ͠ͷ·· SSR ͠Α͏ͱ͢ΔͱɺαʔόϓϩηεͰ͸Ϋ
    ϥΠΞϯτͷετϨʔδʹอଘ͞Ε͍ͯΔϑϥάΛࢀরͰ͖ͳ͍ͨΊɺCSR*3 ࣌ͱͷϨϯμϦϯά
    ݁Ռʹࠩ෼͕ੜ͡·͢ɻ
    CSR ࣌ͷΈ SSR ࣌ͱϨϯμϦϯά݁ՌΛͲ͏ͯ͠΋ม͍͑ͨ৔߹͸ɺॳճͰ null (ۭ) ΛϨϯμ
    Ϧϯάͯ͠ɺͦͷ࣍ʹຊདྷඳը͍ͨ͠ίϯςϯπΛϨϯμϦϯά͢Δख๏͕͋Γ·͢ɻ
    ͔͠͠ɺ͜ͷख๏͸ null ΛϨϯμϦϯάͨ͠Օॴʹ͍ͭͯ SSR ͷҙຯ͕ͳ͘ͳͬͯ͠·ͬͨΓɺ
    ϨϯμϦϯάճ਺͕࠷దԽ͞Ε͍ͯͳ͍ͨΊύϑΥʔϚϯεΛྼԽͤ͞ΔཁҼͱͳΔɺͰ͖Ε͹ආ͚
    Δ΂͖ hucky ͳख๏ʹͳΓ·͢ɻ
    Unleash ͳͲͷ֎෦αʔϏεͷ DB Ͱ feature flag Λ؅ཧ͢Ε͹ SSR ࣌ʹ΋εςʔλεΛऔಘͰ
    ͖ΔͨΊ͜ͷ໰୊͸ղফ͞Ε·͕͢ɺ։ൃ؀ڥʹ͓͍ͯσόοά΍ QA ࡞ۀΛߦ͏৔߹ʹ feature
    Flag Λ࣮ߦ؀ڥ͝ͱʹ੾Γସ͍͑ͨέʔεͳͲɺΫϥΠΞϯτͰ΋ feature Flag Λ؅ཧ͍ͨ͠έʔ
    ε͕͋Γ·͢ɻ
    ΫϥΠΞϯτͷετϨʔδͰ feature flag ͷঢ়ଶΛ؅ཧͭͭ͠໰୊ͳ͘ SSR Ͱ͖ΔΑ͏ʹ͢Δͨ
    Ίʹɺࠓճ͸ Service Worker Λ׆༻͢Δ͜ͱͰղܾΛࢼΈ·͢ɻ
    1.2 Service Worker ͱ͸
    Service Worker ͱ͸ωοτϫʔΫϓϩΩγͷΑ͏ͳৼΔ෣͍Λ͢Δϒϥ΢β্Ͱಈ࡞͢ΔϫʔΧ
    Ͱ͢ɻ
    ΫϥΠΞϯτ͔Βͷ HTTP ϦΫΤετͳͲΛτϦΨͱͨ͠Πϕϯτ͕ൃߦ͞ΕɺϦΫΤετʹର
    ͯ͠ϦιʔεͷΩϟογϡΛฦ٫ͨ͠ΓͳͲͷॲཧ͕ϝΠϯϓϩηεͱ͸ผͷεϨουͰฒྻͰߦ͑
    *3 Client Side Rendering ͷུ
    2

    View full-size slide

  7. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.2 Service Worker ͱ͸
    ·͢ɻ
    Service Worker Λ࢖༻͢Δʹ͸ɺ Service Worker ಺ͰͷॲཧΛهड़ͨ͠ JavaScript ϑΝΠϧΛ
    ϗεςΟϯάͯ͠ɺnavigator.serviceWorker.register("path/to/serviceWorker.js") Λ
    ࣮ߦ͢Δ͜ͱͰϒϥ΢βʹ Service Worker Λొ࿥Ͱ͖·͢ɻ
    React ʹ͓͍ͯ͸ొ࿥༻ͷ JavaScript Λ༻ҙͯ͠εΫϦϓτλάΛ index.html ʹهࡌ͢Δ͜ͱ
    Ͱ Service Worker Λొ࿥͢Δ͔ɺ Service Worker Λొ࿥͢Δ custom hook Λ༻ҙ͠·͢ɻ
    Ϧετ 1.2: serviceWorkerHooks.ts
    1: const useRegisterServiceWorker = () => {
    2: useEffect(() => {
    3: const register = async () => {
    4: if (!("serviceWorker" in navigator)) {
    5: return;
    6: }
    7:
    8: const registration = await navigator.serviceWorker
    9: // Next.js ͷ public σΟϨΫτϦʹεΫϦϓτϑΝΠϧΛ഑ஔ
    10: .register("/serviceWorker.js")
    11: .catch((error) => {
    12: if (error instanceof Error) {
    13: return error;
    14: }
    15:
    16: throw Promise.reject(error);
    17: });
    18:
    19: if (registration instanceof Error) {
    20: console.log("Service Worker registration failed: ", registration);
    21: return;
    22: }
    23:
    24: console.log(
    25: "Service Worker registration successful with scope: ",
    26: registration.scope
    27: );
    28: };
    29:
    30: register();
    31: }, []);
    32: };
    Service Worker Λొ࿥͢Δ custom hook Λ༻ҙͨ͠৔߹͸άϩʔόϧͰ࣮ߦ͞ΕΔՕॴʹϚ΢
    ϯτ͢ΔΑ͏ʹ͠·͢ɻ
    register ϝιου͸ɺ͢Ͱʹಉ͡ Service Worker Λొ࿥͍ͯ͠Δ৔߹͸Α͠ͳʹΠϯετʔϧॲ
    ཧΛεΩοϓ͠·͢ɻ
    3

    View full-size slide

  8. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.3 HTTP ϦΫΤετΛϓϩΩγ͢Δ
    1.3 HTTP ϦΫΤετΛϓϩΩγ͢Δ
    Service Worker Ͱ͸ΫϥΠΞϯτ͔Βͷ HTTP ϦΫΤετΛϓϩΩγ͢Δػೳ͕͋Γ·͢ɻ
    ϖʔδͷ SSR ݁ՌΛαʔό͔Βऔಘ͢Δࡍʹ΋ HTTP ϦΫΤετ͕૸ΔͷͰɺ Service Worker
    Ͱ༗ޮԽ͢Δ feature toggle ͷϑϥά໊ΛϦΫΤετͷϔομʹ෇༩͠·͢ɻ
    ϦΫΤετϔομʹ feature flag ͷ৘ใΛؚ·ͤΔ͜ͱͰɺΫϥΠΞϯτͰϑϥάΛ؅ཧ͠ͳ͕Β
    SSR ࣌ʹ feature flag Λϔομ͔ΒऔΓग़͢͜ͱ͕Ͱ͖ΔΑ͏ʹ͠·͢ɻ
    Ϧετ 1.3: serviceWorker.js
    1: self.addEventListener("fetch", (event) => {
    2: if (process.env.NODE_ENV === "production") {
    3: return;
    4: }
    5:
    6: const callback = async () => {
    7: const baseRequest = event.request.clone();
    8:
    9: // ϔομʔʹ feature toggle ͷ৘ใΛ෇༩ͨ͠ HTTP ϦΫΤετΛੜ੒
    10: const request = await appendFeatureToggleRequest(baseRequest);
    11:
    12: return fetch(request);
    13: };
    14:
    15: event.respondWith(callback());
    16: });
    FetchEvent ͷ respondWith ϝιουΛ࢖༻͢Δ͜ͱͰɺΠϕϯτΛൃߦ͢ΔτϦΨͱͳͬͨ
    HTTP ϦΫΤετΛϓϩΩγͰ͖·͢ɻ
    ·ͨɺ ຊ൪؀ڥͰ͸ HTTP ϦΫΤετΛϓϩΩγ͠ͳ͍Α͏ʹ؀ڥม਺Λݟͯ֘౰؀ڥͷ৔߹ʹ
    ॲཧΛΩϟϯηϧ͠·͢ɻ
    1.4 feature toggle ؅ཧ
    Service Worker ͸ඇಉظʹಈ࡞͢ΔͨΊɺಉظॲཧΛඞཁͱ͢Δ session storage ΍ local s
    torage ͸࢖͏͜ͱ͕Ͱ͖·ͤΜɻ
    ϒϥ΢βʹ͸ indexedDB ͱ͍͏ඇಉظʹ௨৴Ͱ͖Δܰྔͳ DB ͕༻ҙ͞Ε͍ͯΔͨΊɺ feature
    toggle ͷ؅ཧʹ͸͜ΕΛ࢖༻͠·͢ɻ
    Ϧετ 1.4: featureToggleDb.ts
    1: const DB = {
    4

    View full-size slide

  9. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.4 feature toggle ؅ཧ
    2: featureToggle: {
    3: name: "featureToggle",
    4: version: 1,
    5: storeNames: ["featureToggles"],
    6: },
    7: } as const;
    8:
    9: const openDb = async (db: keyof typeof DB): Promise => {
    10: return new Promise((resolve, reject) => {
    11: const requst = indexedDB.open(DB[db].name, DB[db].version);
    12:
    13: requst.onupgradeneeded = async () => {
    14: switch (db) {
    15: case "featureToggle": {
    16: await migrationFeatureToggles(requst.result);
    17: return;
    18: }
    19: }
    20: };
    21:
    22: requst.onsuccess = () => {
    23: resolve(requst.result);
    24: };
    25:
    26: requst.onerror = () => {
    27: reject(requst.error);
    28: };
    29:
    30: requst.onblocked = () => {
    31: reject(requst.error);
    32: };
    33: });
    34: };
    35:
    36: const initialFeatureToggles = {
    37: test: true,
    38: };
    39:
    40: const migrationFeatureToggles = (db: IDBDatabase): Promise => {
    41: return new Promise(async (resolve, reject) => {
    42: const objectStore = db.createObjectStore(DB.featureToggle.storeNames[0], {
    43: keyPath: "name",
    44: });
    45:
    46: objectStore.transaction.oncomplete = () => {
    47: const transaction = db.transaction(
    48: DB.featureToggle.storeNames[0],
    49: "readwrite"
    50: );
    51:
    52: const featureToggleStore = transaction.objectStore(
    53: DB.featureToggle.storeNames[0]
    54: );
    55:
    5

    View full-size slide

  10. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.5 feature toggle ͷ SSR ରԠ
    56: Object.entries(initialFeatureToggles).map(([flagName, enabled]) => {
    57: featureToggleStore.add({ name: flagName, enabled });
    58: });
    59:
    60: resolve();
    61: };
    62:
    63: objectStore.transaction.onerror = () => {
    64: reject(objectStore.transaction.error);
    65: };
    66: });
    67: };
    indexedDB Λ࢖༻͢Δʹ͸ɺ window.indexedDB.open ϝιουΛ࢖༻͠·͢ɻ
    indexedDB ͷ open ϝιουΛ࣮ߦ͢Δࡍʹ͸ DB ໊ͱ 0 ΑΓେ͖͍ͷ೚ҙͷ version Λࢦఆ͠
    ·͢ɻ
    ࢦఆͨ͠ version ͷ DB ͕·ͩ࡞੒͞Ε͍ͯͳ͚Ε͹ onupgradeneeded event ͕ൃߦ͞ΕΔͷ
    Ͱɺ͜ͷΠϕϯτൃߦ࣌ʹ feature flag Λ؅ཧ͢Δ ObjectStore Λ࡞੒͠·͢ɻ
    ObjectStore ͱ͸ɺ RDB Ͱ͍͏ςʔϒϧͷΑ͏ͳ΋ͷͰɺ ObjectStore ࡞੒࣌ʹ keyPath ͱ͍
    ͏ index Λ࡞੒͠·͢ɻ
    ObjectStore ͷσʔλૢ࡞͸͢΂ͯτϥϯβΫγϣϯ಺Ͱߦ͍·͢ɻ
    1.5 feature toggle ͷ SSR ରԠ
    SSR ݁ՌΛϦΫΤετ͢Δࡍʹ Service Worker ͰϦΫΤετϔομ಺ʹ feature toggle ৘ใΛ
    ࡌͤͯɺαʔόϓϩηεͰ֘౰ϔομͷ৘ใΛऔΓग़͠·͢ɻ
    Ϧετ 1.5: featureToggleDb.ts
    1: export const getFeatureToggles = async () => {
    2: return new Promise(async (resolve, reject) => {
    3: const db = await openDb("featureToggle").catch((error) => {
    4: if (error instanceof DOMException) {
    5: return error;
    6: }
    7:
    8: return Promise.reject(error);
    9: });
    10:
    11: if (db instanceof Error) {
    12: console.log(db);
    13: return;
    14: }
    15:
    16: const transaction = db.transaction(
    6

    View full-size slide

  11. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.5 feature toggle ͷ SSR ରԠ
    17: DB.featureToggle.storeNames[0],
    18: "readonly"
    19: );
    20:
    21: const featureToggleStore = transaction.objectStore(
    22: DB.featureToggle.storeNames[0]
    23: );
    24:
    25: const request = featureToggleStore.getAll();
    26:
    27: request.onsuccess = () => {
    28: resolve(request.result);
    29: db.close();
    30: };
    31:
    32: request.onerror = () => {
    33: reject(request.error);
    34: db.close();
    35: };
    36: });
    37: };
    Ϧετ 1.6: serviceWorker.js
    1: const appendFeatureToggleRequest = async (request: Request) => {
    2: const defaultHeaders = Object.fromEntries(request.headers.entries());
    3:
    4: const featureToggles = await getFeatureToggles();
    5:
    6: const enabledToggleNames = featureToggles
    7: .filter(({ enabled }) => enabled)
    8: .map(({ name }) => name)
    9: .join(",");
    10:
    11: const appendFeatureToggleRequest = new Request(request, {
    12: headers: {
    13: ...defaultHeaders,
    14: ["Dev-Feature-Toggle"]: enabledToggleNames,
    15: },
    16: });
    17:
    18: return appendFeatureToggleRequest;
    19: };
    20:
    21: self.addEventListener("fetch", (event) => {
    22: if (process.env.NODE_ENV === "production") {
    23: return;
    24: }
    25:
    26: const callback = async () => {
    7

    View full-size slide

  12. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.5 feature toggle ͷ SSR ରԠ
    27: const baseRequest = event.request.clone();
    28:
    29: // ϔομʹ feature toggle ͷ৘ใΛ෇༩ͨ͠ HTTP ϦΫΤετΛੜ੒
    30: const request = await appendFeatureToggleRequest(baseRequest);
    31:
    32: return fetch(request);
    33: };
    34:
    35: event.respondWith(callback());
    36: });
    Ϧετ 1.7: index.tsx
    1: const Home = ({ featureToggle }) => {
    2: return (
    3: <>
    4: {featureToggle?.test ? new : old}
    5: >
    6: );
    7: };
    8:
    9: export default Home;
    10:
    11: const httpHeadersToEnabledToggleNames = (
    12: httpHeaders: IncomingHttpHeaders
    13: ) => {
    14: const toggleHeader = httpHeaders["Dev-Feature-Toggle".toLowerCase()];
    15:
    16: const value = Array.isArray(toggleHeader) ? toggleHeader[0] : toggleHeader;
    17:
    18: const enabledToggleNames = value?.split(",");
    19:
    20: return enabledToggleNames;
    21: };
    22:
    23: const generateFeatureFlags = (enabledToggleNames?: string[]) => {
    24: if (process.env.NODE_ENV === "production") {
    25: return initialFeatureToggles;
    26: }
    27:
    28: const enabledToggleEntries = enabledToggleNames?.map(
    29: (flagName) => [flagName, true] as const
    30: );
    31:
    32: const toggles = {
    33: ...initialFeatureToggles,
    34: ...Object.fromEntries(enabledToggleEntries ?? []),
    35: };
    36:
    37: return toggles;
    8

    View full-size slide

  13. ୈ 1 ষ Service Worker Λհͨ͠ feature toggle ؅ཧ 1.6 ऴΘΓʹ
    38: };
    39:
    40: export const getServerSideProps = async (
    41: context
    42: ) => {
    43: const enabledToggleNames = httpHeadersToEnabledToggleNames(
    44: context.req.headers
    45: );
    46: const toggles = generateFeatureFlags(enabledToggleNames);
    47:
    48: return {
    49: props: {
    50: featureToggle: toggles,
    51: },
    52: };
    53: };
    ϦΫΤετϔομʹࡌͤͨ feature toggle ͸ getServersideProps ಺Ͱऔಘ͠ Page ͷ props ʹઃ
    ఆ͠·͢ɻ
    ϖʔδ͝ͱʹϔομΛऔಘ͢Δ͜ͱͰɺ feature toggle Λඞཁͱ͠ͳ͍ϖʔδ͸੩తੜ੒͢ΔͳͲ
    ࠷దԽ͞ΕΔΑ͏ʹ͠·͢ɻ
    1.6 ऴΘΓʹ
    ͜ͷΑ͏ʹͯ͠ΫϥΠΞϯτͰ feature toggle Λ؅ཧ͠ͳ͕Β SSR ʹରԠͰ͖·͢ɻ
    ϖʔδͷԼҐ૚ͰϚ΢ϯτ͞ΕΔίϯϙʔωϯτͰ feature toggle Λ࢖༻ͯ͠ϨϯμϦϯάΛ෼
    ذͤ͞Δͱ͖ʹ͸ React.Context Λ࢖༻͢Δ͜ͱΛݕ౼ͯ͠΋ྑͦ͞͏Ͱ͢ɻ
    ࠓճͷ͜ͷ Service Worker Λ༻͍ͨ feature toggle ͷ؅ཧํ๏͸ API ϞοΫΛ͢ΔͨΊͷπʔ
    ϧ ʮMock Service Worker*4ʯ ʹண૝ΛಘͯԠ༻ͨ͠ྫʹͳΓ·͢ɻ
    Service Worker Λ׆༻͢Δ͜ͱͰ΋ͬͱ͓΋͠Ζ͍͜ͱ͕Ͱ͖ͦ͏ͳؾ͕͢ΔͷͰҾ͖ଓ͖ݚڀ
    ͍͖ͯ͠·͢ɻ
    *4 MSW: https://mswjs.io/
    9

    View full-size slide

  14. ୈ 2 ষ
    Haskell ͷ੩తαΠτδΣωϨʔλʔ
    ଟ͘ͷϓϩάϥϛϯάݴޠʹ͸੩తͳ Web ϖʔδΛੜ੒͢ΔͨΊͷΞϓϦέʔγϣϯͰ͋Δ
    ʮ੩తαΠτδΣωϨʔλʔʯ͕ଘࡏ͠·͢ɻͨͱ͑͹༗໊ͳ΋ͷͰɺRuby ͷ Jekyll*1 ΍ Go ͷ
    Hugo*2 ͳͲ͕͋Γ·͢Ͷɻࠓճ͸ϓϩάϥϛϯάݴޠ Haskell ͷ੩తαΠτδΣωϨʔλʔΛ঺հ
    ͠·͢ɻ
    Haskell
    Haskell ͸࣍ͷΑ͏ͳಛ௃Λ࣋ͭϓϩάϥϛϯάݴޠͰ͢ɻ
    • ڧྗͳ੩తܕ෇͚ʢܕϨϕϧϓϩάϥϛϯάͳͲ΋Մೳʣ
    • ڧྗͳϝλϓϩάϥϛϯάʢTemplate Haskell ͳͲʣ
    • ஗ԆධՁʢࣜ͸ར༻͢ΔλΠϛϯά·ͰධՁ͞Εͳ͍ʣ
    • ڧྗͳฒߦॲཧʢܰྔεϨου΍ιϑτ΢ΣΞτϥϯβΫγϣϯϝϞϦͳͲʣ
    Haskell Ͱ͸ɺখͯ͘͞γϯϓϧͳؔ਺Λ༻ҙ͠ɺͦΕΒΛؔ਺߹੒͢ΔܗͰϓϩάϥϜΛ૊Έཱ
    ͯΔͷ͕جຊʹͳ͍ͬͯ·͢ɻ·ͨɺϞφυͱ Do ه๏ͱ͍͏ػೳΛར༻ͯ͠ɺ͋Δछͷ಺෦ DSL
    ͷΑ͏ͳॻ͖ํΛ࣮ݱͨ͠Γ͠·͢ɻࠓճ͸͋Δҙຯɺ੩తαΠτδΣωϨʔλʔΛ૊ΈཱͯΔͨΊ
    ͷ಺෦ DSL ͷΑ͏ͳه๏Λར༻͠·͢ɻ
    2.1 Hakyll
    Haskell ͷ੩తαΠτδΣωϨʔλʔͷ͏ͪɺ࠷΋༗໊ͳͷ͕ Hakyll*3 Ͱ͢ɻHakyll ͷόʔδϣ
    ϯ 1.0 ͕ग़ͨͷ͕ 2010 ೥*4Ͱ͢ͷͰɺൺֱతྺ࢙ͷ௕͍ϓϩδΣΫτͰ͢Ͷɻଞͷϓϩάϥϛϯά
    ݴޠͷ੩తαΠτδΣωϨʔλʔͱͷେ͖ͳҧ͍͸ɺ੩తαΠτδΣωϨʔλʔࣗ਎Λϓϩάϥϛϯ
    ά͢Δ఺ʹ͋Γ·͢ɻ
    *1 https://jekyllrb.com
    *2 https://gohugo.io
    *3 https://jaspervdj.be/hakyll/
    *4 https://github.com/jaspervdj/hakyll/tree/hakyll-1.0
    11

    View full-size slide

  15. ୈ 2 ষ Haskell ͷ੩తαΠτδΣωϨʔλʔ 2.1 Hakyll
    ଞͷϓϩάϥϛϯάݴޠͷ੩తαΠτδΣωϨʔλʔͷ৔߹ɺ༻ҙ͞Εͨ CLI πʔϧ΁ҎԼͷ
    ϑΝΠϧ܈Λ༩͑ͯ੩తͳ Web αΠτͷϑΝΠϧ܈Λੜ੒͠·͢ɿ
    • YAML ΍ JSON Ͱॻ͔ΕͨઃఆϑΝΠϧ
    • ֤ϓϩάϥϛϯάݴޠʹͷͬͱͬͨςϯϓϨʔτه๏ΛؚΉ HTML ϑΝΠϧͳͲ
    • ϚʔΫμ΢ϯͳͲͰهड़ͨ͠هࣄ༻ͷจॻ
    Hakyll ͷ৔߹ɺͦ΋ͦ΋༻ҙ͞Εͨ CLI πʔϧ͕͋Γ·ͤΜɻࣗ਎Ͱϓϩάϥϛϯάͯ͠ CLI
    πʔϧΛ༻ҙ͠ɺ্هͷΑ͏ͳϑΝΠϧ܈Λ࢖ͬͨπʔϧΛ࡞੒͠·͢ɻ
    ੩తαΠτδΣωϨʔλʔΛ࡞Δ
    Hakyll ͷެࣜαΠτ͔ΒαϯϓϧίʔυΛҾ༻͖ͯ͠·ͨ͠ɻ
    main :: IO ()
    main = hakyll $ do
    -- Static files
    match "images/*" $ do
    route idRoute
    compile copyFileCompiler
    -- Pages
    match "post/*.md" $ do
    route $ setExtention "html"
    compile $ pandocCompiler
    >>= loadAndApplyTemplate "templates/post.html" defaultContext
    ͬ͘͟Γ 2 ͭͷϒϩοΫʹ෼͔Ε͍ͯΔͷ͕Θ͔Δ͸ͣͰ͢ɻલ൒͸੩తͳϑΝΠϧΛͦͷ··
    ίϐʔ͍ͯ͠Δ͚ͩͰ͢ɻޙ൒͸ϚʔΫμ΢ϯͰهड़ͨ͠จॻΛ Pandoc*5 Λར༻ͯ͠ HTML ʹ
    ม׵͍ͯ͠·͢ɻPandoc ͸ Haskell ੡ͷΞϓϦέʔγϣϯͰɺϚʔΫμ΢ϯͱ HTML ͷ΄͔ʹɺ
    LaTeX ΍ reStructuredText ͳͲ͞·͟·ͳϚʔΫΞοϓݴޠΛ૬ޓม׵ͯ͘͠Ε·͢ɻ͜ͷ࣌ʹ
    ࢖͏ HTML ςϯϓϨʔτΛ loadAndApplyTemplate ؔ਺Ͱࢦఆ͍ͯ͠·͢ɻ
    ֤ϒϩοΫʹ͸ 3 ͭͷϑΣʔζ͕͋Γ·͢ɿ
    • match : ೖྗͱͯ͠࢖͏ϑΝΠϧͷબ୒
    • route : ग़ྗઌͷϑΝΠϧͷࢦఆʢ֦ுࢠ΍ύεΛॻ͖׵͑Δʣ
    • compile : ೖྗϑΝΠϧͷத਎Λॻ͖׵͑Δ
    લ൒Ͱ࢖͍ͬͯΔ idRoute ͷ id ͸ identity ͷུশͰɺ߃౳ࣸ૾ʢ\x -> xʣͷ͜ͱΛࢦ͍ͯ͠
    ·͢ɻͭ·Γɺग़ྗઌͷϑΝΠϧ໊͸ೖྗͱಉ͡ͱ͍͏͜ͱͰ͢ͶɻloadAndApplyTemplate ͷ࠷
    ޙʹ౉͍ͯ͠Δ defaultContext ͸ςϯϓϨʔτ಺Ͱར༻Ͱ͖Δม਺܈ͰɺContext ܕʹͳ͍ͬͯ
    *5 https://pandoc.org
    12

    View full-size slide

  16. ୈ 2 ষ Haskell ͷ੩తαΠτδΣωϨʔλʔ 2.1 Hakyll
    ·͢ɻͨͱ͑͹ɺλά΍೔෇ͳͲΛςϯϓϨʔτͰهड़͍ͨ͠৔߹͸ɺdefaultContext Ͱ͸ͳࣗ͘
    ਎ͰΧελϚΠζͨ͠΋ͷΛ࢖͍·͢ɻ
    ྫɿΞʔΧΠϒϖʔδʹϖʔδωʔγϣϯΛೖΕΔ
    ࣗ਎Ͱ੩తαΠτδΣωϨʔλʔΛΧελϚΠζͰ͖ΔྫΛ঺հ͠·͢ɻ·ͣ͸ɺաڈʹ౤ߘͨ͠
    هࣄͷҰཡϖʔδʢΞʔΧΠϒϖʔδʣΛੜ੒͢Δ Rule Λॻ͍ͯΈ·͢ɿ
    create ["archive.html"] $ do
    route idRoute
    compile $ do
    posts <- loadAll "posts/*"
    let archiveCtx = mconcat
    [ listField "posts" defaultContext (pure posts)
    , defaultContext
    ]
    makeItem ""
    >>= loadAndApplyTemplate "templates/archive.html" archiveCtx
    ΞʔΧΠϒϖʔδ͸ɺࠓ·ͰͷͱҟͳΓݩʹͳΔهࣄ΍σʔλ͕ͳ͘ɺθϩ͔Β HTML ϑΝΠϧ
    Λੜ੒͢ΔͷͰ match ؔ਺ͷ୅ΘΓʹɹ create ؔ਺Λ࢖͍·͢ɻΞʔΧΠϒϖʔδͷςϯϓϨʔ
    τͰ͸هࣄͷҰཡʢλΠτϧͱϦϯΫʣΛ౉ͯ͠ϧʔϓͰॲཧ͢Δ͜ͱΛߟ͑·͢ɻͦͷ৘ใΛ౉͢
    ͨΊʹɺઐ༻ͷ Context Λ archiveCtx ͱͯ͠࡞͍ͬͯ·͢ɻ
    ͜ͷ··ͩͱɺ͢΂ͯͷهࣄ͕ 1 ϖʔδʹζϥʔͬͱฒͿͷͰϖʔδ෼͚ʢϖʔδωʔγϣϯʣΛ
    ͠·͢ɻHakyll Ͱϖʔδωʔγϣϯ͢Δʹ͸ buildPaginateWith ؔ਺ͱ paginateRules ؔ਺Λ
    ࢖͍·͢ɿ
    archive <- buildPaginateWith
    (return . paginateEvery 10) -- 10هࣄͣͭʹ۠੾Δ
    "posts/*"
    (\pageNum -> fromFilePath ("archive/" ++ show pageNum <.> "html"))
    paginateRules archive $ \pageNum pat -> do
    route idRoute
    compile $ do
    posts <- loadAll pat
    let archiveCtx = mconcat
    [ listField "posts" defaultContext (return posts)
    , paginateContext archive pageNum
    , defaultContext
    ]
    makeItem ""
    >>= loadAndApplyTemplate "templates/archive.html" archiveCtx
    13

    View full-size slide

  17. ୈ 2 ষ Haskell ͷ੩తαΠτδΣωϨʔλʔ 2.2 Slick
    ϖʔδωʔγϣϯͷೖྗઌͱग़ྗઌͷઃఆΛ buildPaginateWith ؔ਺Ͱ༻ҙͯ͠ paginateRul
    es ؔ਺Ͱग़ྗํ๏Λنఆ͍ͯ͠·͢ɻϖʔδωʔγϣϯ͞ΕͨςϯϓϨʔτʹ͸ɺલޙͷϖʔδ൪
    ߸ͱϦϯΫͳͲͷ৘ใ͕ඞཁͰ͢ΑͶʁ ͦΕΛ૊ΈཱͯΔͷ͕ paginateContext ؔ਺Ͱ͢ɻଞ͸
    جຊɺલͷঢ়ଶͱಉ͡Ͱ͢Ͷɻ
    2.2 Slick
    Haskell ͷ੩తαΠτδΣωϨʔλʔ͸ఆظతʹ৽͍͠ίϯηϓτͷ΋ͷ͕ग़͖ͯ·͢ɻࠓճ͸
    Hakyll ͷ΄͔ʹࢲ͕ར༻͍ͯ͠Δ Slick*6 ΋঺հ͠·͢ɻ
    Slick ΋ Hakyll ͱಉ͡Α͏ʹɺ੩తαΠτδΣωϨʔλʔࣗମΛϓϩάϥϛϯά͠·͢ɻSlick ͷ
    README ʹ͸ Hakyll ͷܽ఺ͱͯ͠ɺHakyll ༻ͷಠࣗϞφυͷ෦෼ʹ͍ΖΜͳίϯςΩετ͕Ӆ
    ณ͞Ε͓ͯΓɺશମ૾Λ೺Ѳ͢Δͷ͕ඇৗʹࠔ೉ͳ఺͕͋͛ΒΕ͍ͯ·͢ɻͦͷͨΊɺΑΓγϯϓϧ
    Ͱѻ͍΍͍͢΋ͷΛ໨ࢦ͍ͯ͠ΔΑ͏Ͱ͢ɻSlick ͷಛ௃ͱͯ͠ɺ಺෦తͳॲཧΛ΄͔ͷ͘͠Έʹҕ
    Ͷ͍ͯΔ఺͕͋͛ΒΕ·͢ɿ
    • ϏϧυγεςϜʹ͸ Shake*7 Λར༻͍ͯ͠Δʢఏڙ͢ΔαϒίϚϯυ΍Ϗϧυ݁ՌͷΩϟο
    γϡͳͲʣ
    • Markdown ͔Β HTML ΁ͷม׵͸ Pandoc Λར༻͍ͯ͠ΔʢHakyll ͱಉ͡ʣ
    • ςϯϓϨʔτͷϨϯμϦϯάʹ͸ Mustache*8 Λར༻͍ͯ͠Δ
    Shake ͸ Make ͷ୅ସΛ໨ࢦͨ͠ Haskell Ͱهड़Ͱ͖ΔϏϧυγεςϜͰ͢ɻHaskell ͷσϑΝΫ
    τελϯμʔτͳॲཧܥͰ͋Δ GHC Ͱ΋ར༻͞Ε͍ͯ·͢*9ɻMustache ͸ಛఆͷϓϩάϥϛϯά
    ݴޠʹґଘ͠ͳ͍൚༻ͷςϯϓϨʔτΤϯδϯͰ͢ɻHaskell ࣮૷΋ଘࡏ͠ɺͦΕΛར༻͍ͯ͠·͢ɻ
    ྫɿهࣄͷϖʔδੜ੒
    ྫͱͯ͠ɺϚʔΫμ΢ϯͰهड़͞ΕͨهࣄΛ HTML ʹม׵͢Δ෦෼Λࣔ͠·͢*10ɿ
    data Post =
    Post { title :: String
    , author :: String
    , date :: String
    , image :: Maybe String
    , content :: String
    }
    *6 https://github.com/ChrisPenner/slick
    *7 https://shakebuild.com
    *8 https://mustache.github.io/
    *9 ΑΓਖ਼֬ʹ͸ɺShake Λϕʔεʹͯ͠ GHC ༻ʹ։ൃ͞Ε͍ͯΔ Hadrian ͱ͍͏ϏϧυγεςϜͰ͢ɻhttps:
    //gitlab.haskell.org/ghc/ghc/-/wikis/building/hadrian
    *10 https://github.com/ChrisPenner/slick-template ΑΓൈਮ
    14

    View full-size slide

  18. ୈ 2 ষ Haskell ͷ੩తαΠτδΣωϨʔλʔ 2.3 ऴΘΓʹ
    deriving (Generic, Eq, Ord, Show, FromJSON, ToJSON, Binary)
    buildPosts :: Action [Post]
    buildPosts = do
    paths <- getDirectoryFiles "." ["site/posts//*.md"]
    forP paths buildPost
    buildPost :: FilePath -> Action Post
    buildPost srcPath = cacheAction ("build" :: T.Text, srcPath) $ do
    content <- readFile’ srcPath
    postData <- mmarkdownToHTML’ @Post (T.pack content)
    template <- compileTemplate’ "templates/post.html"
    writeFile’ (outputFolder > dropDirectory1 (srcPath -<.> "html")) $
    T.unpack (substitute template postData)
    convert postData
    ΍͍ͬͯΔ͜ͱ͸ Hakyll ͷͱ͖ͱ΄ͱΜͲಉ͡Ͱ͢ɻ৑௕ʹͳͬͯ·͕͢ɺ୅ΘΓʹશମ૾͕ͭ
    ͔Έ΍͍͢͸ͣͰ͢ɻ
    Slick ͷ৔߹ɺHakyll ͷ Context ܕͷΑ͏ͳςϯϓϨʔτʹ౉͢৘ใΛɺͦΕͧΕͷܕͰಠࣗʹ
    ఆٛ͢Δ͜ͱΛ૝ఆ͞Ε͓ͯΓɺPost ܕ͕ͦΕʹ͋ͨΓ·͢ɻmmarkdownToHTML’ ؔ਺͕ Pandoc
    Λར༻ͯ͠ϚʔΫμ΢ϯΛ HTML ΁ม׵͍ͯ͠·͢ɻͦͷࡍʹɺFront Matter ͷ৘ใΛ Post ܕ
    ΁ม׵͍ͯ͠·͢ɻcontent ϑΟʔϧυͷ෦෼͚ͩ͸ɺFront Matter Ͱ͸ͳ͘ຊจͰ͢ɻcompile
    Template’ ͸ Mustache ͷςϯϓϨʔτϑΝΠϧΛಡΈࠐΈɺsubstitute ؔ਺ͰςϯϓϨʔτ಺
    ͷม਺Λ Post ܕͷ஋Λݩʹஔ͖׵͍͑ͯ·͢ɻcacheAction ؔ਺͸ Shake ͷؔ਺ͰɺϑΝΠϧͷ
    มߋΛݕ஌͠มߋ͕͋ͬͨ৔߹ʹ͚ͩੜ੒͠௚͢෦෼ͷఆٛΛ͍ͯ͠·͢ɻ
    2.3 ऴΘΓʹ
    ࠓճ͸ Haskell ͷ੩తαΠτδΣωϨʔλʔͱͯ͠ݹ͔͘Β࢖ΘΕ͍ͯΔ Hakyll ͱɺൺֱత৽
    ͍͠ Slick Λ঺հ͠·ͨ͠ɻͨͩ୯ʹϚʔΫμ΢ϯͰهࣄΛॻ͖ɺ੩తαΠτΛ࡞Δ͚ͩͰ͋Ε͹
    Jekyll ΍ Hugo Ͱ΋ྑ͍ͱࢥ͍·͢ɻͨͩɺJekyll ΍ Hugo Λ࢖ͬͨ͜ͱΛɺRuby ΍ Go Ͱϓϩ
    άϥϛϯάͨ͠ͱ͸ݴ͍͕͍ͨͰ͢ΑͶʁ ͔͠͠ɺHakyll ΍ Slick Ͱ͋Ε͹ɺHaskell Ͱϓϩάϥ
    ϛϯάͨ͠ͱݴͬͯ΋աݴͰ͸ͳ͍͸ͣͰ͢ɻͰ͢ͷͰɺHaskell Λ࢖ͬͯΈ͍͚ͨͲಛʹॻ͖͍ͨ
    ΞϓϦέʔγϣϯ͕ͳ͍ͱ͍͏ਓ͸ɺࢼ͠ʹ࢖ͬͯΈͯ͸Ͳ͏Ͱ͠ΐ͏͔ɻ
    15

    View full-size slide

  19. ୈ 3 ষ
    Clojure Ͱ࢝ΊΔ࢓༷෼ੳ
    3.1 ͸͡Ίʹ
    Έͳ͞Μɺ࢓༷ॻಡΜͰ͍·͔͢ʁ
    ੈͷதʹ͸࢓༷ॻΛಡΉ͜ͱ΍ઃܭ͢Δ͜ͱ͸ଟ͋͘Γ·͕͢ɺ࣌ʹ࢓༷ॻͷͳ͍ശΛૢ࡞͢Δ
    ඞཁʹഭΒΕΔ͜ͱ͕͋Γ·͢ɻࠓճ͸ͦΜͳ࢓༷ॻͷͳ͍ശΛૢ࡞ͨ͠ͱ͖ʹ࢓༷ॻΛ࿉੒ͨ͠ɺ
    ͪΐͬͱมΘͬͨΤϯδχΞϦϯάʢʁʣΛ঺հ͠·͢ɻ
    ͕͖ͨͩ͠
    ຊষͰ঺հ͢Δ಺༰͸ MIXI ࣾͰ࣮ࡍʹ࢖ΘΕ͍ͯΔσʔλɺ࢓༷ͱ͸ԿΒؔ܎͕͋Γ·ͤΜɻ
    3.2 ঢ়گઃఆ
    ͋ͳͨ͸ɺͱ͋ΔλϫʔσΟϑΣϯεήʔϜͷσόοάΛ͍ͯ͠·͢ɻ
    σόοά಺༰ͱͯ͠͸ɺࢿྉ 1 ͷΫΤετʹ͍ͭͯɺμϛʔͷσʔλΛ࡞ͬͯήʔϜͷڍಈʹᴥᴪ
    ͕ͳ͍͔ΛνΣοΫ͢Δɺͱ͍͏΋ͷͰ͢ɻ
    ͳ͓ɺμϛʔͷσʔλʹ͍ͭͯ͸ɺࢿྉ 2 ͷαϯϓϧΛࢀߟʹదٓௐ੔͢Δඞཁ͕͋Γ·͢ɻ
    17

    View full-size slide

  20. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.2 ঢ়گઃఆ
    ࢿྉ 1
    ਤ 3.1: ΫΤετͷྲྀΕਤ
    18

    View full-size slide

  21. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.2 ঢ়گઃఆ
    ࢿྉ 2
    ։ൃνʔϜ͔Βڞ༗͞Εͨαϯϓϧσʔλͱͦͷઆ໌
    event_quest_sample.json
    {
    "dataId": "event_quest",
    "eventQuestId": "20220801",
    "title": "εϖγϟϧΫΤετ1",
    "updatedAt": "20220715133011",
    "stages": [
    {
    "teki_count": 25,
    "teki": [
    {"id": 1, "level": 60, "count": 15, "type": 1},
    {"id": 2, "level": 55, "count": 10, "type": 1}
    ],
    "teki_syutugen": "0000",
    },
    {
    "teki_count": 40,
    "teki": [
    {"id": 1, "level": 60, "count": 15, "type": 1},
    {"id": 3, "level": 75, "count": 5, "type": 3},
    {"id": 5, "level": 40, "count": 20, "type": 1}
    ],
    "teki_syutugen": "0100",
    },
    {
    "teki_count": 15,
    "teki": [
    {"id": 1, "level": 60, "count": 10, "type": 1},
    {"id": 3, "level": 75, "count": 4, "type": 3},
    {"id": 7, "level": 90, "count": 1, "type": 2}
    ],
    "teki_syutugen": "0230",
    }
    ]
    }
    ։ൃνʔϜ͔Βڞ༗͞Εͨϝοηʔδ.txt
    ఴ෇ͨ͠Ϛελσʔλͷ event_quest_sample.json ΛϕʔεʹΫΤετΛ࡞Ε·͢ɻ
    εςʔδͷઃఆͱͯ͠͸ɺ1ͭ໨ͷεςʔδͰ͸0෼ɺ2ͭ໨ͷεςʔδͰ͸1෼ɺ3ͭ໨ͷεςʔδͰ͸2෼30ඵ
    Ͱఢ͕ग़ݱ͠·͢ɻ 2ͭ໨ͷεςʔδͰதϘε͕5ମɺ3ͭ໨ͷεςʔδͰϘε͕1ମग़ݱ͠·͢ɻ
    ͦΕͧΕͷϚελσʔλ͸ɺ؅ཧը໘͔Βೖߘ͢Δ͜ͱͰ൓өͰ͖·͢ͷͰɺσόοάΑΖ͓͘͠ئ͍͠·͢ɻ
    ಛʹݟͯཉ͍͠؍఺ͱͯ͠͸ɺఢͷλΠϓ͕Ϙε (type = 3) ͷͱ͖ʹϘεͷϚʔΫ͕֘౰ͷఢΩϟϥΫλʹ
    ෇༩͞ΕΔͱ͜ΖͰ͢ɻ
    19

    View full-size slide

  22. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    ͜͜·Ͱདྷͯ໰୊ͱͳΔͷ͕ɺ event_quest_sample.json ʹ͍ͭͯ ๻Β͸Ұ੾ͷ࢓༷Λ஌Βͳ
    ͍ ɺͱ͍͏఺Ͱ͢ɻ
    ៛ີͳ࢓༷Λ༻ҙͯ͠΋Β͏ʹ͸ίετ͕͔͔Γ·͢͠ɺखݩͰ͋Δఔ౓ͷ࢓༷ͷ͋ͨΓΛ͚ͭ
    ͯɺ͍͔ͭ͘ͷٙ໰఺͸։ൃνʔϜ΁దٓڞ༗ͭͭ͠σόοάΛ׬ྃͤ͞ͳ͚Ε͹ͳΓ·ͤΜɻ
    ্ઃఆʹ͓͍ͯద༻Ͱ͖ΔΞϓϩʔν͸͍͔ͭ͋͘Δͱࢥ͍·͕͢ɺࠓճ͸ ࠓ͋ΔσʔλΛύʔ
    εͯ͠ܕʹམͱ͠ࠐΈɺٯʹੜ੒Ͱ͖ΔΑ͏ͳπʔϧΛ࡞Δ ͜ͱͰରԠͯ͠Έ·͢ɻ
    Clojure ͱܕ
    Clojure ͱ͍͏ͷ͸ಈతϓϩάϥϛϯάݴޠͷҰͭͰɺ͔ͳΓಠಛͷܕʹ͍ͭͯͷߟ͑Λ͍࣋ͬͯ
    ·͢ɻͦͯ͜͠ͷಠಛͳܕ΁ͷߟ͑ํ͕ɺࠓճͷΑ͏ͳಾͳσʔλͷ෼ੳʹඇৗʹ༗ྗͳπʔϧͱͳ
    Γ·͢ɻ
    ࠓճ͸ Clojure Ͱ༗ྗͳܕͷఆٛΛิॿ͢ΔϥΠϒϥϦͱͯ͠ malli *1 Λར༻͖ͯ͠·͢ɻ
    ·ͣ͸ Level ͱ͍͏ 1 ͔Β 100 ͷ int ͷ஋ ͷܕΛఆٛͯ͠Έ·͢ɻ
    small_sample1.clj
    (ns domain.sample
    (:require [malli.core :as m]))
    (def Level [:and :int [:> 0] [:<= 100]]) ; int Ͱ 0 ΑΓେ͖͘ 100 ҎԼͰ͋Δ
    ;; ΠϯλϓϦλςετ
    (m/validate Level 0) ; => false
    (m/validate Level 1) ; => true
    (m/validate Level 100) ; => true
    (m/validate Level 101) ; => false
    ͜ͷΑ͏ʹɺ type Level int (golang) ͷΑ͏ͳܕఆٛΑΓ΋ৄࡉʹσʔλͷܕΛఆٛɾνΣο
    ΫͰ͖·͢ɻಈతܕ෇͖ݴޠͳΒͰ͸ͷܳ౰Ͱ͕͢ɺ ্ͷྫͷΑ͏ʹ Clojure ͸ɺJavaScript ͷΑ
    ͏ͳ΄͔ͷಈతܕ෇͖ݴޠΑΓ΋ɺσʔλͷܕʹ͍ͭͯஸೡʹѻ͑Δͷ͕ັྗͷҰͭͰ͢ɻ
    ·ͨ͜ͷಈతͳੑ࣭Λར༻ͯ͠ɺ࣍ͷΑ͏ͳؔ਺Λ࡞Δ͜ͱͰɺσʔλͷαϯϓϦϯά͕Ͱ͖·͢
    *2ɻ
    *1 https://github.com/metosin/malli
    *2 malli ͷػೳΛ࢖͑͹αϯϓϦϯάؔ਺͸ࣗಈੜ੒Ͱ͖ΔͷͰ͕͢ɺنଇੑΛ΋ͨͤͨαϯϓϦϯάͳͲ͕೉͍ͨ͠Ίɺ
    ຊষΛॻ͍ͨਓ͸ಠࣗͰؔ਺Λ࡞ΔํΛ͓קΊ͍ͯ͠·͢
    20

    View full-size slide

  23. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    small_sample2.clj
    (ns domain.sample
    (:require [malli.core :as m]))
    (def Level [:and :int [:> 0] [:<= 100]]) ; int Ͱ 0 ΑΓେ͖͘ 100 ҎԼͰ͋Δ
    (defn my-validate [spec value]
    (or
    ;; ࢓༷Λຬ͍ͨͯ͠Ε͹ true
    (m/validate spec value)
    ;; ࢓༷Λຬ͍ͨͯ͠ͳ͚Ε͹ΤϥʔΛ౤͛Δ
    (throw (ex-info "invalid spec" {:spec spec :value value}))))
    (defn generate-level []
    ;; αϯϓϦϯάͨ͠ฦΓ஋͕࢓༷Λຬ͍ͨͯ͠ͳ͚Ε͹ΤϥʔΛ౤͛Δ
    {:post [(my-validate Level %)]}
    (inc (rand-int 100)))
    ;; ΠϯλϓϦλςετ
    (generate-level) ; => 54 etc.
    ·ͨ Clojure ͷ͜ͷख๏ͷ΋͏ҰͭͷڧΈͱͯ͠ɺ σʔλؒͷؔ܎Λܕʹམͱ͠ࠐΊΔ ͱ͍͏΋
    ͷ͕͋Γ·͢ɻ۩ମతͳαϯϓϧͱͯ͠ɺ ఢͷϦετ teki ͱఢͷ਺Λද͢ teki_count Λ࣋ͭ
    teki_setting ͱ͍͏஋ ͷܕΛఆٛͯ͠Έ·͢ɻ
    small_sample3.clj
    (ns domain.sample
    (:require [malli.core :as m]))
    (def Level [:and :int [:> 0] [:<= 100]]) ; int Ͱ 0 ΑΓେ͖͘ 100 ҎԼͰ͋Δ
    (def Teki
    [:map
    [:id [:int]]
    [:level Level] ; લʹఆٛͨ͠ Level ܕ
    [:count [:and :int [:> 0]]]
    [:type [:enum 1 2 3]]])
    (def TekiSetting
    [:and
    [:map ; ҎԼͷΩʔΛ࣋ͭࣙॻߏ଄
    [:teki-count [:and :int [:> 0]]] ; teki-count ͸ 0 Ҏ্
    [:teki [:vector {:min 1} Teki]]]
    [:fn (fn [{:keys [teki-count teki]}]
    ;; teki-count ͸ (-> teki :count) ͷ߹ܭͱҰக͢Δ
    (= teki-count (apply + (map :count teki))))]])
    ;; ΠϯλϓϦλςετ
    21

    View full-size slide

  24. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    (m/validate TekiSetting
    {:teki-count 30
    :teki [{:id 1 :level 2 :count 10 :type 1}
    {:id 2 :level 3 :count 20 :type 1}]}) ; => true
    (m/validate TekiSetting
    {:teki-count 30
    :teki [{:id 1 :level 2 :count 10 :type 1}
    {:id 2 :level 3 :count 30 :type 1}]}) ; => false
    Clojure Λ࢖ͬͯϓϩάϨογϒʹ࢓༷Λ෼ੳͯ͠ΈΔ
    ͜ͷઅͰ͸͍Α͍Αݩͷ event_quest_stages.json Λ෼ੳ͍͖ͯ͠·͢ɻ
    ෼ੳखॱ͸ҎԼͷ 2 εςοϓ͔ΒͳΓ·͢ɻ
    1. Ͱ͖Δ͚ͩݻఆ஋ͷܕ (= ཁૉ 1 ͷ Enum) Λ෇͚͍ͯ͘
    2. ৄࡉͳ࢓༷͕Θ͔ͬͨͱ͜ΖͷܕͷղऍΛ޿͍͛ͯ͘
    22

    View full-size slide

  25. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    1. Ͱ͖Δ͚ͩݻఆ஋ͷܕΛ෇͚͍ͯ͘
    ·ͣ๻Β͕Ͱ͖ΔҰ൪খ͞ͳ͜ͱͱͯ͠͸ɺ༩͑ΒΕͨσʔλͷΈ͕ਖ਼͍͠ܕ Λ࡞Δ͜ͱͰ͢ɻ
    ͦͷதͰɺσόοάʹΑΓৄࡉͳ࢓༷͕ඞཁͳ஋ΛϦετΞοϓ͍͖ͯ͠·͢ɻ
    event_quest.clj
    (ns domain.event_quest
    (:require [malli.core :as m]))
    ;; ࢓༷
    (def Level [:and :int [:> 0] [:<= 100]]) ; int Ͱ 0 ΑΓେ͖͘ 100 ҎԼͰ͋Δ
    (def Teki
    [:map
    [:id [:int]]
    [:level Level] ; લʹఆٛͨ͠ Level ܕ
    [:count [:and :int [:> 0]]]
    [:type [:enum 1 2 3]]]) ; type ͸ 1 ~ 3 ͚ͩʁ
    (def EventQuestStage
    [:and
    [:map
    [:teki-count [:and :int [:> 0]]]
    [:teki [:vector {:min 1} Teki]]]
    [:teki-syutugen [:and
    :string
    [:fn is-valid-time?]]]
    [:fn (fn [{:keys [teki-count teki]}]
    ;; teki-count ͸ (-> teki :count) ͷ߹ܭͱҰக͢Δ
    (= teki-count (apply + (map :count teki))))]])
    (def EventQuest
    [:map
    [:data-id [:= "event_quest"]] ; ͜Ε͸ݻఆʁ
    [:event-quest-id [:= "20220801"]] ; ೔෇ʁ
    [:title [:= "εϖγϟϧΫΤετ1"]] ; ΫΤετλΠτϧ? จࣈྻ௕͸Ͳ͏ͩΖ͏
    [:updated-at [:= "20220715133011"]] ; yyyyMMddHHmmss ͬΆͦ͏
    [:stages [:vector {:min 3 :max 3} EventQuestStage]]]) ; stage ͸ 3 ͭݻఆʁ
    ;; ΠϯλϓϦλςετ
    (m/validate EventQuest
    {:data-id "event_quest"
    :event-quest-id "20220801"
    :title "εϖγϟϧΫΤετ1"
    :updated-at "20220715133011"
    :stages [{:teki-count 25
    :teki [{:id 1 :level 60 :count 15 :type 1}
    {:id 2 :level 55 :count 10 :type 1}]
    :teki-syutugen "0000"}
    {:teki-count 40
    23

    View full-size slide

  26. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    :teki [{:id 1 :level 60 :count 15 :type 1}
    {:id 3 :level 75 :count 5 :type 3}
    {:id 5 :level 40 :count 20 :type 1}]
    :teki-syutugen "0100"}
    {:teki-count 15
    :teki [{:id 1 :level 60 :count 10 :type 1}
    {:id 3 :level 75 :count 4 :type 3}
    {:id 7 :level 90 :count 1 :type 2}]
    :teki-syutugen "0230"}]}) ; => true
    ;; utils
    (defn is-valid-time? [t]
    (if (not= (count t) 4)
    false
    (let [[min sec] (->> t (partition-all 2) (map (partial apply str)))]
    (and
    (= min (re-matches #"\d{2}" min))
    (= sec (re-matches #"[0-5][0-9]" sec))))))
    24

    View full-size slide

  27. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    2. ৄࡉͳ࢓༷͕Θ͔ͬͨͱ͜ΖͷܕͷղऍΛ޿͍͛ͯ͘
    1. ͷεςοϓͰݻఆ஋ͷαϯϓϧ͕Ͱ͖ͨͱ͜ΖͰɺ࣍ʹ a) αϯϓϧσʔλΛ΋͏গ͠΋Β͏
    b) ։ൃνʔϜ͔Βٙ໰఺ʹ্͕ͬͨσʔλ߲໨ͷ࢓༷ΛώΞϦϯά͢ΔɺͳͲͯ͠ɺσόοάʹඞ
    ཁͳσʔλੜ੒͕Ͱ͖Δͱ͜Ζ·ͰܕͷղऍΛ޿͍͖͛ͯ·͢ɻ
    ͨͱ͑͹ҎԼͷΑ͏ͳܕఆٛʹͳΔ͜ͱ͕ߟ͑ΒΕ·͢ɻ
    event_quest.clj
    (ns domain.event_quest
    (:require [malli.core :as m]))
    ;; ࢓༷
    (def Level [:and :int [:> 0] [:<= 100]]) ; int Ͱ 0 ΑΓେ͖͘ 100 ҎԼͰ͋Δ
    (def Teki
    [:map
    [:id [:int]]
    [:level Level] ; લʹఆٛͨ͠ Level ܕ
    [:count [:and :int [:> 0]]]
    [:type [:enum 1 2 3 4 5]]]) ; type ͸ 1 ~ 5
    (def EventQuestStage
    [:and
    [:map
    [:teki-count [:and :int [:> 0]]] ; teki-count ͸ 0 Ҏ্
    [:teki [:vector {:min 1 :max 10} Teki]] ; teki ͸ 10 छྨ·Ͱ
    [:teki-syutugen [:and
    :string
    [:fn is-valid-time?]]]]
    [:fn (fn [{:keys [teki-count teki]}]
    ;; teki-count ͸ (-> teki :count) ͷ߹ܭͱҰக͢Δ
    (= teki-count (apply + (map :count teki))))]])
    (def EventQuest
    [:map
    [:data-id [:= "event_quest"]]
    [:event-quest-id [:and :string [:fn is-valid-date?]]] ; ೔෇
    [:title [:string {:min 1 :max 20}]] ; λΠτϧ͸ 20 จࣈҎ಺
    [:updated-at [:and :string [:fn is-valid-datetime?]]] ; yyyyMMddHHmmss
    [:stages [:vector {:min 3 :max 5} EventQuestStage]]]) ; stage ͸ 3 ~ 5
    ;; ΠϯλϓϦλςετ
    (m/validate EventQuest
    {:data-id "event_quest"
    :event-quest-id "20220801"
    :title "εϖγϟϧΫΤετ1"
    :updated-at "20220715133011"
    :stages [{:teki-count 25
    :teki [{:id 1 :level 60 :count 15 :type 1}
    {:id 2 :level 55 :count 10 :type 1}]
    :teki-syutugen "0000"}
    25

    View full-size slide

  28. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.3 ࢓༷ͷ෼ੳΛ͠Α͏
    {:teki-count 40
    :teki [{:id 1 :level 60 :count 15 :type 1}
    {:id 3 :level 75 :count 5 :type 3}
    {:id 5 :level 40 :count 20 :type 1}]
    :teki-syutugen "0100"}
    {:teki-count 15
    :teki [{:id 1 :level 60 :count 10 :type 1}
    {:id 3 :level 75 :count 4 :type 3}
    {:id 7 :level 90 :count 1 :type 2}]
    :teki-syutugen "0230"}]})
    ;; utils
    (defn is-valid-time? [t]
    (if (not= (count t) 4)
    false
    (let [[min sec] (->> t (partition-all 2) (map (partial apply str)))]
    (and
    (= min (re-matches #"\d{2}" min))
    (= sec (re-matches #"[0-5][0-9]" sec))))))
    (defn is-valid-date? [t]
    (try
    (java.time.LocalDate/parse
    t
    (java.time.format.DateTimeFormatter/ofPattern "uuuuMMdd"))
    true
    (catch java.time.format.DateTimeParseException e
    false)))
    (defn is-valid-datetime? [t]
    (try
    (java.time.LocalDate/parse
    t
    (java.time.format.DateTimeFormatter/ofPattern "uuuuMMddHHmmss"))
    true
    (catch java.time.format.DateTimeParseException e
    false)))
    26

    View full-size slide

  29. ୈ 3 ষ Clojure Ͱ࢝ΊΔ࢓༷෼ੳ 3.4 ऴΘΓʹ
    3.4 ऴΘΓʹ
    ࠓճ͸ Clojure Λ༻͍ͯσʔλ͔Β࢓༷Λ෼ੳ͍ͯ͘͠ɺͱ͍͏ͪΐͬͱมΘͬͨΤϯδχΞϦϯ
    άΛ঺հ͍͖ͯ͠·ͨ͠ɻݱ࣮Ͱ͸͋·Γى͜Βͳ͍γνϡΤʔγϣϯͱ͸ࢥ͍·͕͢ɺಈతʹܕΛ
    ෇͚͍ͯ͘͜ͱɺܕΛϦϑΝΫλ͍ͯ͘͜͠ͱɺͱ͍ͬͨಛʹ੩తܕ෇͖ݴޠͰ͸ΊͬͨʹܦݧͰ͖
    ͳ͍ࣄ৅ʹ͍ͭͯݟฉΛ޿Ί͍ͯͨͩ͘ҰॿʹͳΕ͹ͱࢥ͍·͢ɻ
    ·ͨ࢓༷ʹ͸ stringɺint ͱ͍ͬͨجຊσʔλܕ৘ใͷΈΛॻ͘ͷͰ͸ͳ͘ɺࠓճ Clojure Ͱ෼ੳ
    ͨ͠Α͏ͳ໌֬ͳܗʹ·ͱΊΒΕΔͱɺ෼ੳख͕ؒল͚σόοάͳͲ͕ΑΓεϜʔζʹਐΉͷͰɺۃ
    ྗஸೡͳهड़͕Ͱ͖ΔͱΑͦ͞͏Ͱ͢ɻ
    (ཉΛݴ͑͹ ࠓճͷΑ͏ͳϓϩάϥϜͰ࢓༷͕૊·Ε͍ͯΔͱɺσόοάͳͲ͕΍Γ΍͍͢ͷͰɺ
    ֤։ൃνʔϜͷٕज़ελοΫʹ߹Θͤͯద੾ͳݴޠɾπʔϧΛ࠾༻͢Δͷ΋Α͍Ͱ͠ΐ͏)
    27

    View full-size slide

  30. ୈ 4 ষ
    Rust ͷ Axum Λ࢖ͬͨ API αʔό
    ։ൃ
    4.1 ͸͡Ίʹ
    ฐࣾͰ͸ XFLAG PARK ͱ͍͏ήʔϜɾΞχϝɾԻָͳͲ͞·͟·ͳδϟϯϧͷ֞ࠜΛ௒͑ͨະ
    ମݧͷ LIVE ΤϯλʔςΠϝϯτγϣʔΛ։࠵͍ͯ͠·͢ɻࠓ೥ͷ XFLAG PARK 2022 Ͱ͸ɺγ
    εςϜͷҰ෦Ͱ Rust Λ༻͍ͨ։ൃΛ͠·ͨ͠ɻຊষͰ͸ɺRust Ͱ API αʔόΛ։ൃ͢ΔͨΊͷϑ
    ϨʔϜϫʔΫͰ͋Δ Axum ʹ͍ͭͯ঺հ͠·͢ɻ
    ຊষͷର৅ऀ
    • Rust Ͱ API αʔόΛ࡞ͬͯΈ͍ͨਓ
    • Actix Web ΍ Rocket ͳͲͷ΄͔ͷ Rust ͷ Web ϑϨʔϜϫʔΫΛ࢖ͬͨࣄ͕͋Δਓ
    Axum
    Axum*1͸ Rust ͷඇಉظϥϯλΠϜΛ࡞͍ͬͯΔ Tokio ͷνʔϜ͕։ൃ͍ͯ͠Δ Web ϑϨʔϜ
    ϫʔΫͰ͢ɻTokio ͷΤίγεςϜΛϑϧͰѻ͑Δͱ͜Ζ΍ tower ΍ hyper ͳͲͷڧྗͳϥΠϒϥ
    Ϧͱͷ࿈ܞ͕Ͱ͖Δ఺͕ಛ௃Ͱ͢ɻ
    SeaORM
    SeaORM*2͸ async ରԠͷ O/R ϚούͰόοΫΤϯυʹ sqlx Λ࠾༻͍ͯ͠·͢ɻ·ͨɺActixɺ
    Tokioɺasync-std ͷ 3 ͭͷඇಉظϥϯλΠϜʹରԠ͍ͯ͠·͢ɻΑΓݹ͔͘Β Rust ͷ O/R Ϛού
    ͱͯ͠࢖ΘΕ͍ͯΔ Diesel ͱൺֱ͢ΔͱɺDiesel ͸ίϯύΠϧ࣌ʹܕ͕֬ఆ͢Δͷʹର͠ SeaORM
    *1 Axumɿ https://github.com/tokio-rs/axum
    *2 SeaORMɿ https://www.sea-ql.org/SeaORM/
    29

    View full-size slide

  31. ୈ 4 ষ Rust ͷ Axum Λ࢖ͬͨ API αʔό։ൃ 4.2 ToDo ΞϓϦͷ API Λ࡞Δ
    ͸࣮ߦ࣌ʹܕཱ͕֬͢ΔΑ͏ͳڍಈΛ͠·͢ɻ
    4.2 ToDo ΞϓϦͷ API Λ࡞Δ
    Axum Ͱͷ API αʔό։ൃʹ͍ͭͯ؆୯ʹ஌ΕΔΑ͏ ToDo ΞϓϦͷ API Λ࡞ΔαϯϓϧΛࣔ
    ͠·͢ɻ
    *3
    Router ͷ࡞Γํ
    Axum ͷ Router ͸ҎԼͷΑ͏ͳܗͰ࣮૷Ͱ͖·͢ɻ
    src/main.rs
    pub struct AppState {
    pub db: DatabaseConnection,
    }
    #[tokio::main]
    async fn main() {
    let mut opt = ConnectOptions::new(env::var("DB_HOST")
    .expect("DB_HOST is not defined"));
    opt.max_connections(10000)
    .min_connections(5)
    .connect_timeout(Duration::from_secs(8))
    .idle_timeout(Duration::from_secs(8))
    .sqlx_logging(true);
    let db: DatabaseConnection = Database::connect(opt)
    .await
    .expect("Database connection failed");
    let app_state = Arc::new(AppState { db });
    let addr = SocketAddr::from((
    [0, 0, 0, 0],
    env::var("PORT")
    .expect("PORT is not defined")
    .parse::()
    .unwrap(),
    ));
    if let Err(e) = axum::Server::bind(&addr)
    .serve(app(app_state).into_make_service())
    .await
    {
    panic!("{:?}", e)
    }
    }
    *3 ղઆ͢Δ࣮૷ͷίʔυຊମɿ https://github.com/Taillook/axum-seaorm-todo
    30

    View full-size slide

  32. ୈ 4 ষ Rust ͷ Axum Λ࢖ͬͨ API αʔό։ൃ 4.2 ToDo ΞϓϦͷ API Λ࡞Δ
    fn app(app_state: Arc) -> Router {
    Router::new()
    .route(
    "/todo",
    get(handler::todo::get_todo_list).post(handler::todo::post_todo),
    )
    .layer(AddExtensionLayer::new(app_state))
    }
    ·ͣɺapp ؔ਺Ͱ Router Λ࡞Γ·͢ɻroute ͱ͍͏ؔ਺ͰύεͱϋϯυϥΛ Router ʹఆٛ͢Δࣄ
    ͕Ͱ͖·͢ɻ͜ͷϋϯυϥ͸ϝιουνΣΠϯͷܗͰ౉͢ܗࣜʹͳΓ·͢ɻ·ͨɺlayer ͱ͍͏ؔ਺
    Ͱ͸ AddExtensionLayer ͱ͍͏ߏ଄ମͱ߹Θͤͯঢ়ଶΛ࣋ͭࣄ͕Ͱ͖·͢ɻ͜ͷྫͰ͸ AppState
    ͱ͍͏ DB ΁ͷ઀ଓ৘ใΛ࣋ͬͨߏ଄ମΛঢ়ଶͱͯ͠อ͍࣋ͯ͠·͢ɻ͜͜Ͱ layer ͱͯ͠ఆٛͨ͠
    ஋͸֤ϋϯυϥͰҾ਺ͱͯ͠ݺͼग़ͯ͠ѻ͍·͢ɻ
    main ؔ਺Ͱ͸ AppState ͷ৘ใͱαʔόͷ PORT ৘ใΛఆٛ͠ Router Λ࣮ࡍʹಈ͔͍ͯ͠
    ·͢ɻ
    Handler ͷ࡞Γํ
    Handler ͸ҎԼͷΑ͏ʹ࣮૷͠·͢ɻ
    src/handler/todo.rs
    pub async fn get_todo_list(Extension(state): Extension>)
    -> Response {
    let todo_list = Todos::find().all(&state.db).await;
    match todo_list {
    Ok(todo_list) => (
    StatusCode::OK,
    Json(TodoResponse {
    todo_list: serde_json::from_str::>(
    json!(todo_list).to_string().as_str()
    ).unwrap(),
    }),
    )
    .into_response(),
    Err(err) => (
    StatusCode::INTERNAL_SERVER_ERROR,
    Json(ApiError {
    status: i32::from(StatusCode::BAD_REQUEST.as_u16()),
    title: format!("{:?}", err),
    }),
    )
    .into_response(),
    }
    }
    31

    View full-size slide

  33. ୈ 4 ষ Rust ͷ Axum Λ࢖ͬͨ API αʔό։ൃ 4.2 ToDo ΞϓϦͷ API Λ࡞Δ
    pub async fn post_todo(
    Extension(state): Extension>,
    Json(params): Json,
    _: Auth,
    ) -> Response {
    let todo = todos::ActiveModel {
    todo: Set(params.todo),
    ..Default::default()
    };
    let result = Todos::insert(todo).exec(&state.db).await;
    match result {
    Ok(result) => (
    StatusCode::INTERNAL_SERVER_ERROR,
    Json(PostTodoResponse {
    last_insert_id: result.last_insert_id as i32,
    }),
    )
    .into_response(),
    Err(err) => (
    StatusCode::INTERNAL_SERVER_ERROR,
    Json(ApiError {
    status: i32::from(StatusCode::BAD_REQUEST.as_u16()),
    title: format!("{:?}", err),
    }),
    )
    .into_response(),
    }
    }
    ·ͣɺAxum ͷϋϯυϥ͸ axum::response::IntoResponse ͱ͍͏τϨΠτΛ࣮૷ͨ͠΋ͷΛ
    Ϩεϙϯεͱͯ͠ฦ͘͢͠Έͱͳ͍ͬͯ·͢ɻ͍͔ͭ͘ܗ͕ࣜ͋Γ·͕͢ྫͰ࣮૷͢Δϋϯυϥ͸ (
    http::status::StatusCode, axum::Json) ͱ͍ͬͨܗࣜͰϨεϙϯεΛฦ͠·͢ɻ
    DB ͱͷ࿈ܞ͸ઌड़ͷ AppState ͷίωΫγϣϯΛ࢖͍ɺTodos ͳͲͷ֤ςʔϒϧ͝ͱʹ࣮૷͞
    Εͨؔ਺Λ࢖͍·͢ɻ͜ͷؔ਺ͷ࣮૷͸ࣗಈੜ੒ͰߦΘΕ͍ͯͯ SeaORM ͕ఏڙ͢Δ sea-orm-cli
    Λ༻͍·͢ɻ·ͨɺAppState Λऔಘ͍ͯ͠Δ Extension(state) ΍ Json(params) ͳͲͷҾ਺͸
    Extractor ͱݺ͹ΕɺϦΫΤετͷσʔλΛநग़͢Δ͘͠ΈͰ͢ɻ
    OpenAPI ͱͷ࿈ܞ
    OpenAPI ͱͷ࿈ܞʹ͍ͭͯ͸ݱঢ় Axum ଆͷରԠ͕͞Ε͍ͯ·ͤΜɻPoC ͱͯ͠ͷ࣮૷͸Կ౓
    ͔ٞ࿦͞Ε͍ͯ·͢*4͕௚ۙͰ͸ࣗಈੜ੒౳Ͱ࿈ܞ༻ͷίʔυΛੜ੒͢ΔΑ͏ͳܗͰରԠ͢Δ΄͔ͳ
    ͍Ͱ͢ɻ
    ຊষͰͷྫͰ͸ openapitools/openapi-generator-cli ͷ rust ΦϓγϣϯΛ༻͍ͯ Rust ͷߏ଄ମͷ
    *4 axum Ͱͷ OpenAPI ରԠͷ PoCɿ https://github.com/tokio-rs/axum/pull/459
    32

    View full-size slide

  34. ୈ 4 ষ Rust ͷ Axum Λ࢖ͬͨ API αʔό։ൃ 4.2 ToDo ΞϓϦͷ API Λ࡞Δ
    ΈΛαʔό࣮૷಺Ͱѻ͏ରԠΛऔ͍ͬͯ·͢ɻ
    ೝূ
    Bearer ೝূͳͲ͸ҎԼͷΑ͏ʹ࣮૷͠·͢ɻ
    src/handler/auth.rs
    pub struct Auth;
    pub struct AuthError;
    impl IntoResponse for AuthError {
    fn into_response(self) -> Response {
    let status = StatusCode::UNAUTHORIZED;
    let body = json!({"error": "Unauthorized".to_string()}).to_string();
    (status, body).into_response()
    }
    }
    #[async_trait]
    impl FromRequest for Auth
    where
    B: Send,
    {
    type Rejection = AuthError;
    async fn from_request(req: &mut RequestParts) -> Result {
    use std::env;
    use axum::{
    extract::TypedHeader,
    headers::{authorization::Bearer, Authorization},
    };
    match TypedHeader::>::from_request(req).await {
    Ok(TypedHeader(Authorization(bearer))) => {
    match bearer.token() == env::var("API_KEY")
    .expect("API_KEY is not defined") {
    true => Ok(Auth {}),
    false => Err(Self::Rejection {}),
    }
    }
    Err(_) => Err(Self::Rejection {}),
    }
    }
    }
    FromRequest ͱ͍͏τϨΠτΛ࣮૷͢ΔࣄͰϋϯυϥͷҾ਺ʹ͋Δ Extension ΍ Json ͳͲͷ
    33

    View full-size slide

  35. ୈ 4 ষ Rust ͷ Axum Λ࢖ͬͨ API αʔό։ൃ 4.3 ͓ΘΓʹ
    Extractor*5Λ࣮૷͢Δࣄ͕Ͱ͖·͢ɻ͜ͷ࣮૷Ͱ͸ AuthorizationΛऔಘ͠ɺbearer
    .token() ͱ API_KEY ؀ڥม਺ͷϚονΛऔΔࣄͰೝূΛߦ͍ͬͯ·͢ɻJWT ͷݕূͷΑ͏ͳ
    Extractor Λ࡞Γ͍ͨ৔߹ʹ͓͍ͯ΋ from_request ؔ਺಺ͷॲཧΛมߋ͢ΔࣄͰ༰қʹ࣮૷Ͱ͖
    ·͢ɻ
    4.3 ͓ΘΓʹ
    ຊষͰ͸ Rust ͷ Axum Λ࢖ͬͨ API ͷ࣮૷ʹ͍ͭͯ঺հ͠·ͨ͠ɻRust Ͱ API αʔόΛ࡞Δ
    ํ΁ͷࢀߟʹͳΕ͹ͱࢥ͍·͢ɻ
    ͨͩ͠ɺൃల్্ͳϑϨʔϜϫʔΫͱ͍͏ͷ΋͋ΓόʔδϣϯΞοϓʹ͍͍ͭͯ͘ؾ߹͍΋ඞཁͰ
    ͸͋Γ·͢ɻ
    *5 axum ͷ Custom Extractorɿ https://docs.rs/axum/0.1.1/axum/extract/index.html#defining-custom-
    extractors
    34

    View full-size slide

  36. ୈ 5 ষ
    ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ
    5.1 ຊষʹ͍ͭͯ
    ࢲ͕औΓ૊ΉϓϩδΣΫτʹ͓͍ͯதֶߍ΁ͷιϑτ΢ΣΞఏڙ΍ֶशࢦಋΛ਺ଟ࣮͘ࢪͨ͠ɻͦ
    ͷதͰ࣮ફͨ͠໰୊෼ੳ΍ݕূͱϑΟʔυόοΫΛऔΓೖΕͯͷվળʹ͍ͭͯৼΓฦͬͯ੔ཧ͠ɺι
    ϑτ΢ΣΞ։ൃࣄྫͷҰͭͱͯ͠චऀ΋ؚΊͨಡऀ͢΂ͯͷํͷܞΘΔϏδωεʹ׆͔͞Ε͍ͨɻͳ
    ͓ઌʹݴ͓ͬͯ͘ͱɺຊষͰ͸ϓϩάϥϛϯάͱίʔυͷ࿩͸ొ৔͠ͳ͍ɻ

    චऀϓϩϑΟʔϧ
    ήʔϜΛத৺ͱͨ͠ιϑτ΢ΣΞΤϯδχΞͱͯ͠׆ಈ͓ͯ͠ΓɺίϯγϡʔϚήʔϜ΍ϒϥ΢
    βήʔϜͱεϚʔτϑΥϯΞϓϦͷ։ൃɺWeb αʔϏε΍ήʔϜاը΋ܞΘΔɻۙ೥͸ڭҭݱ
    ৔ʹ޲͚ͯɺ
    ʮϓϩάϥϛϯάֶशʯΛਪਐ͢Δߨࢣͱͯͦ͠ͷֶशιϑτ΢ΣΞ΍ΧϦΩϡϥ
    Ϝ։ൃͱซͤͯऔΓ૊ΜͰ͍Δɻ
    LinkedIn: https://www.linkedin.com/in/akira-tanabe/

    ͶΒ͍
    ࢲ͕୲͍ͬͯΔۀ຿Ͱ͋Δ͜ͷϢχʔΫͳऔΓ૊ΈͷཪଆΛ͔͋͠աఔΛৼΓฦΔ͜ͱͰɺ޿ٛͳ
    ιϑτ΢ΣΞιϦϡʔγϣϯʹ͓͚Δ໰୊ղܾࣄྫͱͯ͠࢒͠චऀͱಡऀͷֶͼʹͭͳ͛Δ͜ͱΛओ
    ࢫͱ͢Δ
    35

    View full-size slide

  37. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.1 ຊষʹ͍ͭͯ
    ཁ໿
    • ݱࡏࢲͨͪ͸தֶߍʹରͯ͠ϢχʔΫͳࢧԉ׆ಈΛൃݟ͠ͳ͕Βܧଓతʹ࣮ࢪ͍ͯ͠Δ
    • ࣮ࢪઌ΍಺༰͸͋Β͔͡Ίܾ·͍ͬͯΔΘ͚Ͱ͸ͳ͘ɺ੠Λฉ͖ঢ়گΛݟͯاըΛఏҊ͠ͳ͕
    ΒίϯςϯπΛఏڙ͓ͯ͠Γɺ·ͨ೔ʑͦΕ͸ਐԽ͠ॆ࣮͖͍ͯͯ͠Δ
    • ໰୊ղܾͷࢹ఺Ͱɺ͜Ε·Ͱࢧԉ͕࣮ݱͨ͠աఔͰ͸ͲΜͳ໨తʹ͓͍ͯɺͲͷΑ͏ʹఏࣔ
    ͠ɺͲͷΑ͏ͳ४උΛ͠ɺͲΜͳબ୒Λͨ͠ͷ͔Λྫࣔ͢Δ͜ͱͰɺ͍ͣΕ͔ͷϏδωεͷ֫
    ಘ΍্ཱͪ͛ʹͱͬͯؔ৺͕͋ΔࣄྫͱͳΕ͹ͱࢥ͍ه͢
    • ιϑτ΢ΣΞ։ൃͷࢹ఺Ͱɺͦͷاըͷݟ௨͠ΛͲͷΑ͏ʹཱͯɺͲͷΑ͏ͳཪ෇͚Λ࣋ͪɺ
    ͲͷΑ͏ʹ਱ߦ͔ͨ͠Λྫࣔ͢Δ͜ͱͰɺιϑτ΢ΣΞ੍࡞΍Ϗδωεͷ্ཱͪ͛ɺىۀʹ
    ͱͬͯؔ৺͕͋ΔࣄྫͱͳΓ͏Δ
    TOPICS
    1. ࢲͨͪͷڭҭࢧԉ׆ಈʹ͍ͭͯ
    2. ໰୊
    3. ໰୊ͷ෼ղ
    4. ໨ඪઃఆͱߦಈࢦ਑
    5. ίϯςϯπاըͱ͞·͟·ͳ෼ੳ
    6. ΞΠσΞͷൃ૝ͱࢥߟ
    7. ࠷ޙʹ
    ࢀߟจݙɺҾ༻
    •ʮϏδϣφϦʔΧϯύχʔʯδϜɾίϦϯζʢ˞γϦʔζʣ
    •ʮGIVE ˍ TAKEʯΞμϜɾάϥϯτ
    •ʮϦʔϯɾελʔτΞοϓʯΤϦοΫɾϦʔε
    •ʮRunnnig LeanʯΞογϡɾϚ΢Ϧϟ
    •ʮϏδωεϞσϧδΣωϨʔγϣϯζʯΞϨοΫεɾΦελʔϫϧμʔɺΠϰɾϐχϡʔϧ
    •ʮMeasure What Matters ఻આͷϕϯνϟʔ౤ࢿՈ͕ Google ʹڭ͑ͨ੒ޭख๏ OKRʯδϣ
    ϯɾυʔΞ
    •ʮσβΠϯࢥߟ͕ੈքΛม͑Δ: ΠϊϕʔγϣϯΛಋ͘৽͍͠ߟ͑ํʯςΟϜɾϒϥ΢ϯ
    •ʮܦӦઓུશ࢙ʯࡾ୩ ޺࣏
    36

    View full-size slide

  38. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.2 ࢲͨͪͷڭҭࢧԉ׆ಈʹ͍ͭͯ
    5.2 ࢲͨͪͷڭҭࢧԉ׆ಈʹ͍ͭͯ
    ओͳίϯςϯπ࣮੷͓ΑͼΧϦΩϡϥϜαΠζ
    • ौ୩۠಺ͷެཱɾࢲཱதֶߍतۀࢧԉ͓ΑͼίϯςϯπͱΧϦΩϡϥϜ
    –ʮதֶ૯߹తͳֶशͷ࣌ؒʯ޲͚ςΩεϓϩάϥϛϯάɹ 3 ίϚ૬౰ʢڭࢣ࣮ࢪՄʣ
    –ʮதֶ਺ֶʯ޲͚ίϯύεΛ࢖ͬͨ਺ֶ՝୊ɹ 1 ίϚ૬౰ʢڭࢣ࣮ࢪՄʣ
    –ʮதֶٕज़Պ D ৘ใʯ޲͚ςΩεϓϩάϥϛϯάɹ 8 ίϚ૬౰ʢڭࢣ࣮ࢪՄʣ
    –ʮதֶٕज़Պ D ৘ใʯ޲͚ Python ݴޠϓϩάϥϛϯάɹ 1ʙ4 ίϚ૬౰
    • ಉ۠಺ͷެཱɾࢲཱதֶߍ޲͚ͷύιίϯ෦ܥࢦಋ͓ΑͼίϯςϯπͱΧϦΩϡϥϜ
    –ʮதֶύιίϯ෦׆ಈʯ޲͚ LuaɾPython ϓϩάϥϛϯάɹ 2 ࣌ؒ x7 ೔෼૬౰
    –ʮதֶύιίϯ෦׆ಈʯ޲͚ Unity ήʔϜ੍࡞ϓϩάϥϛϯάɹ 2 ࣌ؒ x4 ೔෼૬౰
    • ΩϟϦΞڭҭɾϓϩάϥϛϯάϫʔΫγϣοϓ
    – தֶੜ޲͚ϓϩάϥϛϯάߨ࠲ɹ 1.5 ࣌ؒ૬౰
    – தֶੜ޲͚ήʔϜ։ൃ Unity ߨ࠲ɹ 3 ࣌ؒ૬౰
    – ΤϯδχΞ৬ߨԋ
    ਤ: ٕज़Պ Python तۀ
    37

    View full-size slide

  39. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.3 ໰୊
    5.3 ໰୊
    ͔͜͜Β͸ɺࢲ͕औΓ૊ΜͰ͍ͯࠓճৄ͘͠ղઆ͍ͨ͠ʮ໰୊ʯͷى͜ΓͱͦͷରԠʹ͍ͭͯࣄྫ
    ঺հͱͯ͠ৄ͍͠ܦҢΛهड़͍ͯ͘͠ɻͳ͓ɺهࡌ͢Δଞऀʹؔ͢Δഎܠ΍ҙࢥʹ͍ͭͯͷ৘ใݯ
    ͸ɺҰൠʹࠂࣔ͞Ε͍ͯΔ΋ͷͷ΄͔ҙਤΛټΜͰςΩετԽͨ͠෦෼΋ଟগ͋Δɻຊষͷझࢫ͸໰
    ୊ղܾख๏ʹ͓͚ΔղܾࣄྫΛɺ޷ҙతʹ෼ੳ͠࿦͡Δ΋ͷͰ͋Γɺ͍ͣΕ͔ͷ૊৫ʹ͓͚Δ಺৘΍
    ໰୊఺ʹ͍ͭͯࢦఠ͢Δҙਤ͸ͳ͍ɻ
    ໰୊ͷ্ཱ͕ͪΓ
    • ओɹ୊ɹɿɹٛ຿ڭҭ΁ͷϓϩάϥϛϯάֶशࢧԉΛ͢Δ
    • ґཔऀɹɿɹौ୩۠
    • ൃɹੜɹɿɹ 2019 ೥౓य़
    a. എܠɹʙֶߍڭҭͰͷϓϩάϥϛϯάֶशͱ͸
    ಺ֳ෎ͷΊ͟͢ Society 5.0 ͷࣾձɻङྌɺ೶ߞɺ޻ۀɺ৘ใʹଓ͘ 5 ظ໨ͱͳΔࣾձ͕໨ࢦ͢΋
    ͷ͸αΠόʔۭؒͱϑΟδΧϧۭؒΛߴ౓ʹ༥߹ͤͨࣾ͞ձɻະདྷʹ޲͚ͯςΫϊϩδͱՊֶٕज़
    ͱͷ༥߹ͳͲɺ૯߹తͳֶशʹऔΓ૊Ή STEAM ڭҭΛਪਐ͢Δจ෦Պֶলɻֶߍʹ͓͚Δ ICT ׆
    ༻ʢ৘ใ௨৴ٕज़ʣͭ·ΓΠϯλʔωοτ΍ PC ͷར༻Λ࣮ࢪ͢Δ֤஍࣏ࣗମɻ৽͍͠ػث΍ιϑτ
    ΢ΣΞ͕ಋೖ͞ΕैདྷͷतۀҎ֎ͷ஌ࣝͱ׆༻͕ٻΊΒΕͯ͘Δڭһઌੜํɻ
    ֶߍ΍ߦ੓ͷͶΒ͏࣮ࢪల։
    ࣮ࢪϞσϧʹ͓͍ͯ͸ɺICT ׆༻ͱϓϩάϥϛϯάֶशʹ͓͍ͯ஍Ҭͱͷͭͳ͕ΓΛ׆͔ͨ͠औΓ
    ૊Έ͕༗ҙٛͱ͞Εɺ஍ҬΫϥϒ΍஍ݩاۀ΍େֶͳͲͱͷͭͳ͕ΓΛ׆͔ͯ͠ࢦಋ͍ͯ͘͜͠ͱ͕
    ྫࣔ͞ΕΔͳͲɺ׭ɾຽɾֶͷ࿈ܞ͕ࠓޙٻΊΒΕ͍ͯ͘ͱ͍͏ɻ
    ڭҭݱ৔ʹ͓͍ͯ͸ɺ৽෼໺ͱͯ͠ʮϓϩάϥϛϯάʯ͕ࢦಋͷൣғʹೖΔதͰֶश಺༰͕·ͩ໛
    ࡧஈ֊ʹ͋Δɻϓϩάϥϛϯά͸ӳޠͱಉ༷ʹશһֶ͕श͢ΔྖҬʹͳΔͱࣔ͞Ε͍ͯΔɻͦͷ࣌Ͳ
    Μͳ՝୊͕ר͖ى͜Δͷ͔ɺ·ͩ༧ଌ͕͔ͭͳ͍ɻ
    38

    View full-size slide

  40. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.3 ໰୊
    b. େ·͔ͳཁ๬͔Βํ਑΁ͷམͱ͠ࠐΈ·Ͱ
    ࢲ͕ͨͪ໰୊ʹऔΓ૊Έͩͨ͠ͷ͸ 2019 ೥౓य़ɻґཔ͍ͯ͠Δͷ͸ौ୩۠ɻऔΓ૊Ή໰୊͸ɺٛ
    ຿ڭҭͰ͜Ε͔Β࢝·Δʮϓϩάϥϛϯάڭҭʯʹֶ͍ͭͯߍΛࢧԉ͢Δͱ͍͏ौ୩۠୲౰෦ॺ͔Β
    ґཔͷ΋ͷɻ࣌ྲྀతʹ࿩୊ʹͳ͍ͬͯΔશࠃతͳ՝୊Ͱ͋Δʮϓϩάϥϛϯάڭҭʯ͕ٛ຿ڭҭͰ΋
    ࣮ࢪ͞ΕΔ͜ͱͱͳΓɺ࣍೥౓Ͱ͋Δ 2020 ೥౓͔ΒখֶߍɺҎ߱Ͱ͸தֶߍɺߴߍͱ࣮ࢪ͞Ε͍ͯ
    ͘ͱ͍͏ɻґཔ͖ͯͨ۠͠ͷখதֶੜ΁͸ͦΕΑΓ 2 ೥લͷฏ੒ 29 ೥ 9 ݄ʢ2017ʣ͔ΒλϒϨοτ
    PC ͕ࢧڅ͞Ε͍ͯΔɻ׆༻͸࢝·͍ͬͯΔ͕΋ͬͱ͜Ε͔Β৳͹͍ͨ͠ͱ͍͏ঢ়گͰ΋͋Δɻ
    ղܾ͢΂͖໰୊ͷൃݟͱେํ਑ͷܾఆɺ୭ʹԿΛఏڙ͢Δͷ͔
    ໰୊ղܾ΁ͷऔΓ૊Έʹ͋ͨͬͯ͸ҙࢥܾఆऀ͕ܾఆΛԼΖͯ͘͠ΕΔ΋ͷͰ͸ͳ͍ɻऔΓ૊Έʹ
    ͋ͨΔࣗ෼ࣗ਎͕Ͳ͏͢Δ͔Λ෼ੳͯ͠ࡦఆ͠ɺऔΓ૊Έ૬खͱࣗΒͷ૊৫ʹ্͛ೝ஌ͱ߹ҙΛಘ
    ΔɻऔΓ૊Έ૬खͱࣗ૊৫૒ํͷظ଴ʹԠ͑Δ͜ͱ͕ٻΊΒΕΔɻ
    ௕ظతͳऔΓ૊ΈΛߦ͏૬ख΍ؔ܎اۀͱͷ࠲૊Έʢొ৔ਓ෺ͱͦͷؔ܎ੑʣΛ૊Ή࣌఺Ͱɺґཔ
    ऀ΁ࣗ෼ͨͪͷ໾ׂͱظ଴ΛͲͷΑ͏ʹҐஔ෇͚Δ͔Λࣔ͞ͳ͚Ε͹ͳΒͳ͍ɻ೤ྔɺݴ͍׵͑Ε͹
    ফඅΧϩϦʔΛͲͷΑ͏ʹઃఆ͢Δ͔΋ॏཁͰ͋Δɻ·ͬͨ͘౿Έࠐ·ͳ͍ख΋͋Ε͹͔ͬ͠Γ΍Δ
    ख΋͋Δɻطଘιϑτ΢ΣΞΛ୳͢ख΋͋Ε͹ࢴͱϖϯΛ࢖͏ख΋͋Δɻ
    ໰୊΁ͷΞϯαʔͱॳಈΛܾΊΔ͜ͱ͔Β໰୊ղܾ͸࢝·Δɻকདྷతʹ࣮ࢪ͞ΕΔͰ͋Ζ͏ࢧԉͷ
    த਎͸Ͳ͏͍͏΋ͷ͔ɺݱঢ়ͩͱͲ͏໰୊͕͋Δͷ͔ɺ
    ʮࢧԉ͢Δʯͱ͸ԿΛͲ͏͢Δ͜ͱ͔ɻৄ͠
    ͍ௐࠪͱ෼ੳ͕ඞཁʹͳΔɻ
    c. ෼ੳํ๏
    ͔͜͜Βड़΂Δʮ໰୊ղܾʯͷʮ໰୊ʯͱ͸ཁٻཁ๬ͷҰͭͰ͋Γɺ
    ʮ͋Δ౰ࣄऀͷ՝୊ʯͱಉٛͩ
    ͱࢥͬͯಡΜͰ΄͍͠ɻ
    ᶗ. 5W1H ෼ੳ
    ෼ղʹ͋ͨͬͯ࿙Εͳ͘ݕ౼Λߦ͏ͷʹศརͩͱͯ͠ࠓճબ୒ͨ͠ख๏͸ΦʔιυοΫεʹ
    ʮ5W1Hʯ
    ɻେੲ͔Β͋ΔجຊͰ͋ͬͯ෠Δਓ΋ଟ͍ͩΖ͏͕͜ͷ࿦఺ͰͷಥͬࠐΈ͕Ͱ͖Δاը͸
    ಴࠳͢Δɻ෼ੳπʔϧ͕͍·Ͳ͖͔Ͳ͏͔͸໰୊Ͱ͸ͳ͘ɺ࿙Εͳ͘μϒΓͳ͘෼ੳ͢ΔʮMECE
    ʢϛʔγʔʣ
    ʯͷϓϩηε͕ͱΕ͍ͯΔ͔ͱ͍͏͜ͱ͕ϙΠϯτͰ͋Δɻ
    1. what ɹԿΛ
    2. who ɹ୭͕
    3. when ɹ͍ͭ
    4. where ɹͲ͜Ͱ
    5. why ɹͳͥ
    6. how ɹͲ͏΍ͬͯ
    39

    View full-size slide

  41. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.3 ໰୊
    ˙ิ଍ 3 ͭ ্ͷ 5 ͚ͭͩͰ͸࣮ࡍʹ͸͞Βʹಥͬࠐ·Εͯ౴͑ΒΕͳ͍ͨΊɺ͜͜ʹৗ༻తʹ໰Θ
    ΕΔࣄ߲Λಠࣗʹ 3 ͭ଍͓ͯ͘͠ɻଞྫʹ฿ͬͯӳޠදهʹ͢Δɻ
    1. can ɹʢͰ͖Δ͜ͱʣ
    2. should ɹʢ΍Δ΂͖͜ͱʗͰͳ͍͜ͱʣ
    3. resist ɹʢ఍߅ʣ
    ˙ର৅ऀ ໰͏߲໨͸୭ͷࢹ఺ʹΑΔ΋ͷ͔Ͱ΋೿ੜ͢Δ΋ͷͰ͋Γɺͨͱ͑͹ʮwhyʯͳͥ΍Δ͔
    ʹ͓͍ͯࣗ෼͕΍Δཧ༝ͱґཔऀ͕΍Δཧ༝͸͓ͦΒ͘ผʹ͋ΔɻΑΓৄࡉʹݕ౼͍ͯ͘͠ͷͰ͋Ε
    ͹ɺ૒ํʹ૊৫΍άϧʔϓͷϨΠϠ͕͋ΓͦΕͧΕผͷҙࢤ΍໨తΛ࣋ͪɺͦͷझࢫΛ౿ऻ͠߹ҙΛ
    औΓ෇͚͍ͯ͘ඞཁ͕͋Δ͜ͱΛߟྀ͠ͳ͚Ε͹ͳΒͳ͍ɻ
    ࠓճ͸ओʹ߹ҙΛಘ͍ͨର৅ͱͯ͠ҎԼࡾऀʹରͯ͠Ͱ͖Δ͚ͩ͘·ͳ͘ड़΂Δ͜ͱʹ౒ΊΔɻ
    ˙ݕ౼ࢹ఺
    1. ґཔऀ
    2. ࣗ૊৫
    3. ࣗ෼ࣗ਎
    ड͚खଆΛʮࣗ૊৫ʯͱʮࣗ෼ࣗ਎ʯʹ෼͚ͯఆٛͨ͠ͷ͸͜ͷऔΓ૊Έಛ༗ͷଆ໘͕͋Δ͔΋͠
    Εͳ͍ɻԾʹґཔऀ͕໌֬ͳϓϩμΫτʢಛఆͷιϦϡʔγϣϯ΍αʔϏε·ͨ͸੡඼ʣΛٻΊͯ
    Φʔμʔ͍ͯ͠ΔͷͰ͋Ε͹ɺ૒ํͷ໨త͕໌֬Ͱ͋Γ஫໨͢ΔՕॴ͸ҟͳΔͩΖ͏ɻࠓճͷࣄྫ
    ͷ৔߹ɺࣗࣾ͸ʮ΍Δ΂͖͜ͱͰ͋Ε͹΍Δʯͱ͍͏ɺཱͪҐஔͱͯ͠தཱతͳ࢟੎Ͱ͋ͬͨɻ·ͨ
    ʮࣗ෼ࣗ਎ʯͷ࢟੎ͱͯ͠΋ଟগҟͳΓɺ
    ʮࠓޙ༗ҙٛʹͳΔݟࠐΈ͕͋Δ͜ͱΛݟग़ͯ͠΍Δ΂͖ʗ
    ΍Βͳ͍΂͖Λࣔ͢ʯͱ͍͏ཱ৔ʹ͋Δɻ͜Ε͔Βࣔ͢ࡾऀͷඍົͳ࿦఺ͱظ଴஋ͷҧ͍ʹ஫໨ͯ͠
    ΄͍͠ɻ
    ᶘ. ࠓճͷ෼ੳํ๏·ͱΊ
    ໰୊ղܾͷจ຺Ͱ 5W1H ʴЋΛ·ͱΊɺ࣍ͷͱ͓ΓͱͳΔɻ
    40

    View full-size slide

  42. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.3 ໰୊
    ˙ͲΜͳ໰୊͔
    1. ԿΛ͢Δ͜ͱͳͷ͔ what
    2. ୭͕΍Δͷ͔ who
    3. ͍ͭͷ͜ͱͳͷ͔ when
    4. ୭ʢͲ͜ʣʹର͢Δ͜ͱͳͷ͔ where
    5. ͳͥ΍Δͷ͔ why
    6. Ͳ͏΍Δ͔ how
    7. ࣗ෼ୡ͸Կ͔Ͱ͖Δͷ͔ can
    8. ࣗ෼ୡ͸ԿΛ͢΂͖Ͱɺ͢΂͖Ͱͳ͍͔ should
    9. ͲΜͳ఍߅ͱো֐͕͋Δͷ͔ resist
    ˙୭ͷࢹ఺͔
    1. ґཔऀ
    2. ࣗ૊৫
    3. ࣗ෼ࣗ਎
    ͜ΕΒΛςϯϓϨʔτͱͯ͜͠Ε͔Βड़΂Δ෼ੳͰ໰͍͍ͯ͘ɻ
    ᶙ. 5W1H Ͱղઆ͢Δࢹ఺ͷॱং
    ͢΂ͯͷ࣌఺Ͱʮґཔऀʯͱʮࣗ૊৫ʯͱʮࣗ෼ࣗ਎ʯͷࢹ఺Ͱͷఆ͕ٛ͋Δ͸ͣͰ͋ΔɻͦΕͧ
    Εͷҙࢥ͕ৗʹಉ࣌ʹଘࡏ͍ͯ͠ΔͨΊͰ͋Γɺಈ͖͕͋Δͱ͖ͦͷ྆ऀؒͷʮ5W1Hʯ͕ඞཁͰ͋
    Δɻͦͷ͢΂ͯΛड़΂Δʹ͸৑௕Ͱ͋Γ·ͨຊষͰ͸ղܾ͍ͨ͠໰୊ͱͦͷղܾํ๏ʹؔ͢ΔྲྀΕΛ
    ղઆ͍ͨͨ͠ΊɺͦΕͧΕͷஈ֊Ͱͷओ໾ʹ͋ͨΔ 1 ͭͷࢹ఺ͣͭͰड़΂Δ͜ͱʹ͢Δɻ
    41

    View full-size slide

  43. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    5.4 ໰୊ͷ෼ղ
    લ߲Ͱڍ͛ͨ·ͱΊํʮ5W1HʯʴЋͰɺཁ๬ͭ·Γղܾ͍ͨ͠໰୊Λ੔ཧ͢Δɻࢹ఺͸·ͣ໰୊
    ఏىΛ͢ΔʮґཔऀʯΛߟ͑ɺґཔऀͷཱ৔ʹͳͬͯڞײ͠ͳ͕Β໰୊΍ҙਤ΍ཧ૝ͳͲΛټΜͰ
    ͍͘ɻ
    ґཔऀʹͱͬͯ
    • ԿΛ͢Δ͜ͱͳͷ͔ what
    – ٛ຿ڭҭ΁ͷϓϩάϥϛϯάֶशࢧԉΛ͢Δ
    • ୭͕΍Δͷ͔ who
    – ׭ຽֶ࿈ܞʹ͓͚Δʮຽʯ
    ɺຽؒͷઐ໳Ո͕΍Δ͜ͱʹҙຯ͕͋Δ
    • ͍ͭͷ͜ͱͳͷ͔ when
    – ͦͷ࣌఺ͷ࣍೥౓ɻ20 ೥౓͔Βͷॱ࣍ඞमԽʹ޲͚Δ
    • ୭ʢͲ͜ʣʹର͢Δ͜ͱͳͷ͔ where
    – ۠಺ͷٛ຿ڭҭɺ20 ೥౓খֶੜͳͲ
    • ͳͥ΍Δͷ͔ why
    – ֶߍڭһ͚ͩͰ͸ϓϩάϥϛϯάྖҬʹ͍ͭͯઐ໳త஌ࣝͷ४උ͕ͳ͍ͨΊऔΓ૊Έ͕
    ͍ͨ
    • Ͳ͏΍Δ͔ how
    – ఏҊͯ͠΄͍͕͠΄͔ͷࣄྫ΋ࢀߟʹ͢Δ
    • ࣗ෼ୡ͸Կ͔Ͱ͖Δͷ͔ can
    – ۠ͷ IT اۀͷίϛϡχςΟΛ׆͔ͯ͠اۀʹڠྗΛཁ੥͢Δ͜ͱ
    • ࣗ෼ୡ͸ԿΛ͢΂͖Ͱɺ͢΂͖Ͱͳ͍͔ should
    – ࣮ࢪͷબ୒͸ֶߍͷ൑அʹΏͩͶΔͨΊ࣮ࢪϝχϡʔͷఏࣔΛ͢Δʢ΂͖ʣ
    – ֶशࢦಋཁྖʹ४ڌ͢Δʢ΂͖ʣ
    • ͲΜͳ఍߅ͱো֐͕͋Δͷ͔ resist
    – ར༻ڭࡐͷ੍໿͕͋Δ͔΋͠Εͳ͍
    – ֶߍଆͷڠྗ͕ಘΒΕͳ͍͔΋͠Εͳ͍
    – ࢠͲ΋͕ͨͪదԠͰ͖ͳ͍͔΋͠Εͳ͍
    42

    View full-size slide

  44. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    a. ৘ใऩू
    จ෦Պֶলͷࢦ਑ͱઌߦࣄྫ
    ICT ػثʢ৘ใ୺຤ʣͷѻ͍΍ϓϩάϥϛϯάʹؔ͢Δֶश͕৽ͨʹ௥Ճ͞ΕΔখֶߍɺϓϩ
    άϥϛϯά΍৘ใʹؔ͢Δֶश಺༰Λ͞Βʹॆ࣮ͤ͞Δதֶߍɻֶशࢦಋཁྖͷվగ͸ฏ੒ 29 ೥
    ʢ2017.3ʣʹެࣔ͞Εɺখֶߍ͸ྩ࿨ 2 ೥౓ʢ2020.4ʣ
    ɺதֶߍ͸ྩ࿨ 3 ೥౓ʢ2021.4ʣ͔Βશ໘࣮ࢪ
    ͞ΕΔɻ௨ৗɺֶशࢦಋཁྖʹ४ڌͨ͠ڭՊॻ͕ڭՊॻग़൛ձ͔ࣾΒ͍͔ͭ͘࡞੒͞Εɺ֤࣏ࣗମ͝
    ͱʹબఆ࠾୒Λܦͯɺڭһ͕ڭՊॻΛ΋ͱʹतۀҊΛ࡞੒͠ࢦಋ͢Δɻ2019 ೥౰࣌ɺڭՊॻ͸·ͩ
    ͳ͔ͬͨɻ
    খֶߍϓϩάϥϛϯάʹؔͯ͠͸ɺࢦఆڭՊͱͯ͠ͷֶश୯ݩ͸ͳ͘ɺطଘͷֶशʹ͞Βʹ ICT
    ڭࡐ΍ϓϩάϥϛϯάΛԠ༻͍ͯ͘͜͠ͱ͕ࣔ͞Ε͍ͯΔɻྫࣔ͞ΕԠ༻͠΍͍͢෦෼ͱͯ͠͸ʮࢉ
    ਺ʯ
    ʮཧՊʯ
    ʮ૯߹తͳֶशͷ࣌ؒʯͱͳΔɻͦͷޙ࣍ୈʹ͖͋Β͔ʹͳ͍ͬͯ͘ཁૉͱͯ͠ʮΞϧΰ
    ϦζϜʯʹؔΘΔ΋ͷ͕৽ͨʹڭՊॻʹࡌͬͨɻ
    தֶߍֶशࢦಋཁྖͰ͸͢Ͱʹϓϩάϥϛϯάʹؔͯ͠ଟগ͸ʮٕज़Պʯʹࡌ͍ͬͯͨɻ಺༰͕Α
    Γ૿͑ͯॆ࣮͠ɺηϯαͷଌఆɺΞΫνϡΤʔλʢϞʔλʣͷར༻ɺ૒ํ޲௨৴ͱ͍ͬͨࢦ਑͕ࣔ͞
    Ε͍ͯΔɻͦͷޙ࣍ୈʹ໌Β͔ʹͳ͍ͬͯ͘ཁૉͱͯ͠ɺ೔ຊޠϓϩάϥϛϯάݴޠΛ͔ͭͬͨղઆ
    Ͱʮ৘ใҊ಺ʯͱʮνϟοτιϑτʯΛ࡞Δͱ͍͏ͷ͕ڭՊॻʹࡌͬͨɻ
    طଘͷख๏
    ˙ϏδϡΞϧϓϩάϥϛϯά ւ֎༗໊ιϑτ΢ΣΞͷʮScratchʯ
    *1ͳͲΛ࢖ͬͨʮϏδϡΞϧϓϩ
    άϥϛϯάʯͰ͸֓೦ֶ͕शͰ͖ήʔϜͳͲͷ࡞඼͕࡞ΕΔɻੈքతʹখֶߍఔ౓ͷϓϩάϥϛϯά
    ֶशखஈͱͯ͠ελϯμʔτͱݴ͑ΔɻϞʔλ΍ηϯαͳͲͱ૊Έ߹ΘͤͨΩοτ͕ڭࡐձ͔ࣾΒ΋
    ൢച͞Ε͓ͯΓ Scratch ͸؆୯ͳػց੍ޚʹ΋༻͍ΒΕ͍ͯΔɻϩϘοτ؝۩ʹ͓͚Δʮϓϩάϥ
    ϛϯάʯͷπʔϧͱͯ͠ఏڙ͞Ε͍ͯΔ͜ͱ΋͋Δɻ·ͨผͷ΋ͷͱͯ͠͸ɺՈఉ༻ήʔϜػͰ΋ஈ
    Ϙʔϧ޻࡞ͱ߹ΘͤͨΩοτʹ͓͍ͯಠࣗͷϏδϡΞϧϓϩάϥϛϯά͕Ͱ͖ɺίϯτϩʔϥೖྗ΍
    ޫηϯαΛ࢖ͬͨ࡞඼͕࡞Εͨɻ
    ʮϚΠϯΫϥϑτʯ
    *2Ͱ͸ɺಛఆͷΤσΟγϣϯʢʙ൛ʣʹ͓͍ͯ֎
    ෦ػೳΛ࢖͏͜ͱͰຊ֨తͳϓϩάϥϛϯά΍ϏδϡΞϧϓϩάϥϛϯά͕Ͱ͖Δ΋ͷ͕͋Δɻͨͩ
    ϏδϡΞϧπʔϧશମͰݴ͑Δ໰୊ʹɺҰఆن໛Ҏ্ͷ࡞඼ʹͳΔͱঢ়ଶ΍શମ͕ݟͮΒ͘ͳΓ࡞੒
    ೉қ౓্͕͕Γෆศ͕͞૿͢ɻ
    *1 Scratch https://scratch.mit.edu/
    *2 Minecraft https://www.minecraft.net/
    43

    View full-size slide

  45. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    ˙Ξϯϓϥάυϓϩάϥϛϯάֶश ICT ػثΛҰ੾࢖ΘͣʹϓϩάϥϛϯάతࢥߟΛֶͿखஈɻ
    ࣄྫͷଟ͘Ͱ͸ΧʔυΛ࢖ͬͯॲཧͷॱং΍಺༰Λߟ͑Δ͜ͱͰ࿦ཧతࢥߟྗ΍ϓϩάϥϛϯάతͳ
    ࢥߟ΁ͷֶͼ΁ͱ݁ͼ෇͚͍ͯΔɻֶशͰ͖Δ෯΍ਂ͞͸ϓϩάϥϛϯάΛ࣮ࡍʹڭ͑ͨ࣌΄Ͳʹ͸
    ࣋ͨͤͮΒ͘ɺػࡐ͕͋Γ࢖͑ΔͷͰ͋Ε͹࢖ͬͨํ͕ྑ͍Մೳੑ͕ߴ͍ɻ
    ˙ϓϩάϥϛϯάֶशతήʔϜ ίϯγϡʔϚػ΍εϚʔτϑΥϯΞϓϦͳͲͰήʔϜͱͯ͠ϓϩά
    ϥϛϯάΛϞνʔϑʹͨ͠΋ͷ͕͍͔ͭ͋͘ΓɺήʔϜ಺ͷߦಈͱͯ͠ϓϩάϥϛϯάతͳೖྗ΍ࢥ
    ߟΛͤ͞Δ΋ͷ͕͋ΔɻϓϨΠϠʔ͕ʮਓʯΛϓϩάϥϛϯάͯ͠࢓ࣄͷޮ཰Λ্͛Δ͜ͱΛߟ͑Δ
    ͱ͍͏΋ͷ͕Ұ෦Ͱྲྀߦͨ͠ɻ
    ʮϚΠϯΫϥϑτʯͰ͸ίϚϯυͱݴΘΕΔΩʔೖྗ΍ͦΕΛ֨ೲ͠
    ໋ͨྩϒϩοΫΛ૊Έ߹ΘͤͨҰ࿈ͷ࢓ֻ͚ΛϓϩάϥϛϯάͰ͖Δɻ͜ΕΒ͸ମݧΠϕϯτͱͯ͠
    ར༻͞ΕΔ͜ͱ͕ଟ͍͕ɺͦͷޙͷ৘ใͰʮϚΠϯΫϥϑτʯʹ͓͍ͯ͸෇Ճཁૉ΋͋ͬͯतۀͰͷ
    ࣄྫ΋͋Δɻ
    ˙ςΩετϓϩάϥϛϯά Web αΠτ্ͳͲͰ JavaScript ౳ͷεΫϦϓτݴޠΛจࣈೖྗͯ͠
    νϡʔτϦΞϧతʹ՝୊Λղ͍͍ͯ͘λΠϓͷֶशڭࡐ͕͋Δɻ೉қ౓ʹ΋෯͕͋ΓࢠͲ΋޲͚ͷ
    ήʔϜ෩ͳ΋ͷ͔Βࣾձਓ޲͚৬ۀ܇࿅޲͚ͷ༗ྉڭࡐ·Ͱ͍͔ͭ͋͘Δɻ͜ͷπʔϧࣗମ͕νϡʔ
    τϦΞϧҎ֎ͷԿ͔ʹͳ͍ͬͯΔέʔϧ͸͋·Γͳ͍ɻ͋Δ͍͸ Scratch ϕʔεͷػث੍ޚιϑτ
    ΢ΣΞʹ͓͍ͯ JavaScript ΍ Python ΁ग़ྗม׵Ͱ͖Δ৔߹͕͋ΓɺεΫϦϓτΛॻ͍ͯ௚઀੍ޚ
    Ͱ͖Δͱݴ͑Δ͕ػثͱηοτߪೖͷ΋ͷʹͳΔɻ
    ˙ʴЋʹΧϦΩϡϥϜͱࢦಋٕज़ ڭࡐͱֶशΧϦΩϡϥϜͱशख़ͨ͠ࢦಋऀ͕͍ͳ͚Ε͹ͳΒͳ
    ͍ɻ͍ͭ͘΋ͷطଘڭࡐιϑτ΢ΣΞʹ͸ֶशΧϦΩϡϥϜ͕େྔʹ༻ҙ͞Ε͓ͯΓɺࣄۀऀ͸ͦΕ
    Λ೥ֹྉۚΛઃఆͯ͠ఏڙ͍ͯ͠Δɻ͋Δ͍͸ઌߦاۀ͸࣏ࣗମͷڠྗͷ΋ͱ੍࡞ͨ͠ΧϦΩϡϥϜ
    ͕͋Γઐ༻ιϑτ΢ΣΞͱͱ΋ʹ࣮ࢪͰ͖Δ΋ͷ΋͋Δɻ
    b. ໰୊ൃݟ ʢ৘ใऩू·ͱΊʣ
    • ະࢀೖͰ͸ख͕ग़͕͍ͨ͠͏͑੒ཱͤ͞ΔͨΊʹ͸ڑ཭ײ͕͔ͳΓ͋Δ
    • খֶੜ΁ͷࢦಋ͕Ͳ͏͍͏΋ͷ͔ͱ͍͏஌ݟ͕ͳ͍͜ͱʹࣗ෼ͨͪͷ೉͠͞΋͋Δ
    • খֶੜ޲͚ϏδϡΞϧϓϩάϥϛϯάͱ࣮༻ϓϩάϥϛϯάͱʹဃ཭͕͋Δ
    • तۀͷࢦ਑͔ΒʮϓϩάϥϛϯάతࢥߟʯΛ࢖ͬͨԠ༻͕ٻΊΒΕ͓ͯΓط੡඼͔ͦΕʹมΘ
    ΔϓϩμΫτʢֶशͰ͖൓Ԡ͕͋Δ΋ͷʣ͕ඞཁ
    • ط੡඼Ͱ͸ݻ༗ͷ੍ݶʹΑͬͯ੡඼ʹର͢ΔϓϩάϥϛϯάҎ֎ͷ܇࿅͕ඞཁʹͳΓʮϓϩά
    ϥϛϯάֶशʯͷൣғΛ௒͑ͳ͚Ε͹ͳΒͳ͍
    44

    View full-size slide

  46. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    c. Ծઆઃఆ
    ৘ใऩू͠ݱࡏͷ໰୊͕ݟ͑ͯ͘Δͱ൒͹ࣗવͱԾઆཱ͕ͬͯ͘ΔɻԾઆͱ͸ɺཪ෇͚͸·ͩͳ͍
    ͕໰୊ͷঢ়گʹࢸΒ͠ΊΔཁૉΛநग़ͨ͠ΓղܾҊΛڍ͛ΔखॱΛࢦ͢ɻࠓճͷέʔεͰ͸ɺͲ͏ࢧ
    ԉΛܭըͯ͠ఏࣔ͢Ε͹ґཔऀͱ͕ࣗࣾ Win-Win Ͱ͋Δ͔Λ໛ࡧ͢Δ͜ͱʹ͋ΔɻԾઆઃఆʹ͸ɺ
    ͍͔ͭ͘ͷํ޲ੑͰྻڍ͍͖ͯ͠࿙Ε͕ͳ͍Α͏ʹݕ౼ͯ͠΋Α͍͕ɺ͜͜Ͱ͸ʮϩδοΫπϦʔʯ
    Λҙࣝͯ͠Ͳ͏͋Δ΂͖͔Λಋ͖ग़ͨ͠ɻ্͔Βॱʹ͓͓Αͦର࿩ܗࣜʹͳ͍ͬͯΔɻ
    ࢧԉ͢΂͖ࢪࡦͷԾઆ
    • ࣗ෼͕ͨͪͰ͖Δ͜ͱΛͨ͠ํ͕Α͍ͷͰ͸
    • ڭһ͕ڭ͑ʹ͍͘೉қ౓ͷ΋ͷΛѻ͍ڭ͑ͨํ͕ت͹ΕΔͷͰ͸
    • ط੡඼ͷࢦಋ͸ͦΕ͕Ͱ͖Δͱ͜Ζ͕͢ΔͷͰฐࣾͰ͸ෆཁͳͷͰ͸
    • ΤϯδχΞͷܦݧଇతʹ͸ʮςΩετϓϩάϥϛϯάʯ͠ͳ͍ͱࣗ༝ʹͳΕͳ͍ͷͰ͸
    • Ͱ͖Δ্͚ͩͷֶ೥Ͱ͋Ε͹ςΩετϓϩάϥϛϯάͰ͖ΔͷͰ͸
    •ʮதֶੜʯʹςΩετϓϩάϥϛϯάΛڭ͑Ε͹Α͍ͷͰ͸
    • ຊۀʹݶΓͳ͍ۙ͘ͷͰशಘίετͳ͘ࢦಋͰ͖ίϯςϯπఏڙͰ͖ΔՄೳੑ͕ߴ͍ͷͰ͸
    ର৅ऀΛதֶੜʹͯ͠΋Α͍ͷͰ͸
    ౰ॳզʑʹࣔ͞Εݟ͍͑ͯͨظ଴ͱձٞମͷۭؾײͱͯ͠͸׬શʹখֶੜࢧԉͩͬͨɻͨͩখֶੜ
    ʹରͯ͠ࢧԉΛ͢Δاۀ͕΄͔ʹ΋͍ͨ͜ͱ͔Βɺ୭΋खΛग़͞ͳ͍தֶੜʹ͢Δ͜ͱΛґཔऀʹ࢕
    ͏ͱର৅ʹೖ͍ͬͯΔͷͰ OK ͕ͰͨɻݟํʹΑͬͯ͸ɺओྲྀ͔Β֎Εͯ཭୤ͨ͠ͱͱΒΕ͔Ͷͳ
    ͍ɻґཔऀͱฐࣾҎ֎ɺͦΕ͸ͳ͍ͱ͍͏ۭؾͩͱײ͍͕ͯͨ͡ڧ͍৴೦ͰਐΉɻ
    ͜ͷ࣌఺Ͱࣗࣾͷݟղͷશମ૾͕ݟ͖͑ͯͨͨΊɺࢹ఺Λʮࣗ૊৫ʯͱ͢Δʮ5W1HʯͰ੔ཧ͢Δɻ
    ࣗ૊৫ʹͱͬͯ
    • ԿΛ͢Δ͜ͱͳͷ͔ what
    – ґཔऀͷ๬ΉࢧԉΛ࣮ࢪ͢Δ
    – ֶशιϑτ΢ΣΞ։ൃ·ͨ͸ΧϦΩϡϥϜߏங
    – ߨࢣͱॿखͷख഑ͱ܇࿅
    • ୭͕΍Δͷ͔ who
    – ༧ࢉ͔͚ͳ͍ൣғͱͯ͠ࢲࣗ਎
    45

    View full-size slide

  47. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    • ͍ͭͷ͜ͱͳͷ͔ when
    – தֶߍ͕ϓϩάϥϛϯάΛ࣮ࢪ͢Δ 2021 ೥౓·Ͱ
    • ୭ʢͲ͜ʣʹର͢Δ͜ͱͳͷ͔ where
    – தֶߍͷओʹٕज़Պ
    • ͳͥ΍Δͷ͔ why
    – IT اۀͱͯ͠஌ݟΛࢠͲ΋ͨͪͷֶशʹؐݩֶ͠ߍ͚ͩͰ͸Ͱ͖ͳ͍ઐ໳஌ࣝΛఏڙ͢
    Δ͜ͱͰ஍Ҭؐݩ͢Δ
    • Ͳ͏΍Δ͔ how
    – ςΩετϓϩάϥϛϯάͷֶशΛԿΒ͔ͷίϯςϯπΛىͯ͜͠ఏڙ͢Δ
    – ֶशίϯςϯπ͸͍Ζ͍Ζͳͱ͜ΖͰ࢖͑ͦ͏ͳࣗࣾఏڙڭࡐͱ͍͏͜ͱͰݕ౼
    • ࣗ෼ୡ͸Կ͔Ͱ͖Δͷ͔ can
    – ιϑτ΢ΣΞ։ൃ΍αʔϏε։ൃͱϓϩάϥϛϯάͰ͋Δ
    – தֶɺߴߍʹ޲͚ͯʮاۀ๚໰ड͚ೖΕʯͱ͍͏ֶߍ͔Βاۀ΁ͷ๚໰Λड͚Δίϯςϯ
    πΛ࣮ࢪ͍ͯ͠ΔͨΊਓ෺૾͕ΠϝʔδͰ͖Δ
    • ࣗ෼ୡ͸ԿΛ͢΂͖Ͱɺ͢΂͖Ͱͳ͍͔ should
    – ϓϩάϥϛϯά͸͢΂͖͕ͩط੡඼ͷࢦಋ͸͓ͦΒ͘͢΂͖Ͱ͸ͳ͍
    • ͲΜͳ఍߅ͱো֐͕͋Δͷ͔ resist
    – தֶߍʹϓϩάϥϛϯάֶशͷࢧԉ͕ෆཁ͔΋͠Εͳ͍
    – ίϯςϯπ͕੒ཱ͠ͳ͍͔΋͠Εͳ͍
    – ੜెֶ͕शΛड͚ೖΕͳ͍͔΋͠Εͳ͍
    d. ݕূ
    Πϕϯτ։࠵ཁ๬͕͋Γίϯςϯπͷ্ཱͪ͛ͱ࣮ূࢼݧ·ͰਐΉʙ
    ґཔऀͷҙ޲ʹΑͬͯɺऔΓ૊Έશମͱ͍ͯͣ͠Ε͔Λֶߍʹ͍࣋ͬͯ͘લʹ·ͣ͸اۀओ࠵ͷֶ
    शΠϕϯτͰͷΞϐʔϧͱ࣮੷ͮ͘ΓΛ͢Δ͜ͱʹͳΔɻΠϕϯτͰର৅ऀ΍ֶश಺༰ʹؔͯ͠σʔ
    λ͕औΕΔɻલ߲Ͱڍ͛ͨԾઆΛ۩ମతʹͯ͠ݕূ͢Δઈ޷ͷػձͷͨΊͲΜͳܗͰ͋Ε 21 ೥౓ʢ2
    ೥ޙʣ࣮ࢪͷίϯςϯπҊΛࡦఆͯ͠ࢼݧʹྟΉɻ͜ͷͱ͖ 2019 ೥౓ 5 ݄ͰՆͷΠϕϯτ։࠵·Ͱ
    ࢒Γ 3 ϱ݄͕ͩͬͨ 20 ೥౓ʹऔΓ૊ΉΞΫγϣϯͷํ޲ੑʹӨڹ͢Δͱߟ͑ΒΕͨɻڠྗऀΛ૿΍
    ͭͭ͠ΠϕϯτࢀՃऀʹ޲͚ͨ։࠵֓ཁ΍໨తͱ͍ͬͨاը΋ࣗΒܝ͛ͳ͚Ε͹ͳΒͳ͍ɻσόΠ
    εʹ͍ͭͯɺ͜ͷ࣌఺Ͱͷ૝ఆσόΠεΛ Android λϒϨοτͱઃఆͨͨ͠Ί͢΂ͯͷૢ࡞͸λο
    νը໘ೖྗ΍όʔνϟϧΩʔϘʔυʹݶఆ͠ɺNexus5 λϒϨοτΛ 30 ୆आΓ͖ͯͯ։࠵ʹྟΜͩɻ
    46

    View full-size slide

  48. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    ˞ͷͪʹ۠ͷ PC ͱͯ͠ Windows λϒϨοτܕ͕ࢧڅ͞Ε͍ͯΔ͜ͱ͔Βޙऀ͕λʔήοτ୺຤ʹ
    ͳΔ
    ୲౰ऀϨϕϧͷঢ়گͱ໨ඪ͕ݟ͖͑ͨͨΊɺࢹ఺Λʮࣗ෼ࣗ਎ʯͱ͢Δʮ5W1HʯͰ੔ཧ͢Δɻ
    ࣗ෼ࣗ਎ʹͱͬͯ
    • ԿΛ͢Δ͜ͱͳͷ͔ what
    – ֶߍͰ࣮ࢪֶ͍ͨ͠शࢧԉͷ࠷খ੡඼ߏ੒ʢMVPʣͱΧϦΩϡϥϜҊΛ࡞੒͢Δ
    – ґཔऀ͕๬ΉֶशΠϕϯτΛ։࠵͠ࢧԉͷ࣮ݱࣗମΛ͢Δ
    • ୭͕΍Δͷ͔ who
    – ΋ͪΖΜࣗ෼ࣗ਎
    • ͍ͭͷ͜ͱͳͷ͔ when
    – 2019 ೥౓Նʢ3 ϱ݄ޙʣͷΠϕϯτ·Ͱʹୡ੒͢Δ
    • ୭ʢͲ͜ʣʹର͢Δ͜ͱͳͷ͔ where
    – ΠϕϯτԠื͖ͯͨ͠தֶੜ
    • ͳͥ΍Δͷ͔ why
    – 20 ೥౓ʢ࣍೥౓ʣ
    ɺ21 ೥౓ʢ࣍ʑ೥౓ʣʹֶߍ΁ΦϑΝʔ͢ΔͨΊͷσʔλऔಘͱલྫͮ
    ͘ΓͷͨΊ
    • Ͳ͏΍Δ͔ how
    –ʢ࠷ऴతʹʣήʔϜ੍࡞తεΫϦϓτͷԠ༻ͱήʔϛϑΟέʔγϣϯʢ՝୊ͷήʔϜԽʣʹ
    ΑΔֶशίϯςϯπΛఏڙ
    – ٕज़తʹʮήʔϜ੍࡞తεΫϦϓτʢΠϕϯτεΫϦϓτͱͯ͠ར༻͞Ε͍ͯΔݴޠʣ
    ʯ͕
    ഑෍෺ͷϥϯλΠϜͰར༻Ͱ͖Δ͔ͷݕূ͕ඞཁ
    • ࣗ෼ୡ͸Կ͔Ͱ͖Δͷ͔ can
    –ʢࢲ͸ʣήʔϜ͕ओ࣠ͷιϑτ΢ΣΞͷఏڙͱςΩετϓϩάϥϛϯάͷࢦಋ
    – ࣍೥౓Ҏ߱Ͳ͏͍͏ల։ʹ͢Δ͔Λݟग़ࣔͤ͠Δਓؒ͸ࣗ෼͔͍͠ͳ͍ʢ։ൃͱࢦಋ͸ࢲ
    ҰਓͳͷͰʣ
    • ࣗ෼ୡ͸ԿΛ͢΂͖Ͱɺ͢΂͖Ͱͳ͍͔ should
    – Α͍ػձΛಀͣ͞ΠϕϯτͰԾઆݕূʹد༩͢ΔσʔλΛͱΔʢ΂͖ʣ
    – ४උظ͕ؒগͳ͍͔ΒͱػձΛಀ͢΂͖Ͱͳ͍
    • ͲΜͳ఍߅ͱো֐͕͋Δͷ͔ resist
    – ίϯςϯπ੍࡞͕ૂ͍௨Γண஍Ͱ͖ͳ͍͔΋͠Εͳ͍
    – ιϑτ΢ΣΞ΍Πϕϯτࣗମ͕ظ଴௨Γ࣮ࢪͰ͖ͳ͍͔΋͠Εͳ͍
    – ݕূ݁Ռͷσʔλ͕ෆຬΛ͔ࣔ͢΋͠Εͳ͍
    ݕূ݁Ռ
    ४උʹ͓͍ͯ։ൃ 2 ϱ݄ͱςετ͓Αͼௐ੔ 1 ϱ݄Λඅ΍͠ιϑτ΢ΣΞ͸ແࣄ։ൃʹ੒ޭͨ͠ɻ
    ΠϕϯτࢀՃऀืूͷ࣌఺Ͱ಺༰ͷܝ͕ࣔඞཁͩͬͨͨΊهࡌ͢Δ಺༰Ͱ࣮֬ʹΰʔϧͰ͖Δͱ֬ఆ
    47

    View full-size slide

  49. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.4 ໰୊ͷ෼ղ
    Ͱ͖Δ·Ͱʹר͖ʹר͍ͯςετΛॏͶͨɻΠϕϯτʹ͸ 25 ਓ΄Ͳͷࣾһ͔Βڠྗ͕ಘΒΕɺखް
    ͘੝େʹ։࠵Ͱ͖ɺ҆৺ͯ͠ΠϕϯτӡӦΛҕͶΔ͜ͱ͕Ͱ͖ͨɻऔಘσʔλͱͯ͠͸ɺதֶੜ͕ς
    Ωετϓϩάϥϛϯά͕͋Δఔ౓·Ͱ࣮ફͰ͖ͨ੒Ռɺͭ·͖ͣ΍͍͢ՕॴɺΞϯέʔτʹΑΔ൓ڹ
    ΛಘΔ͜ͱ͕Ͱ͖ͨɻͦΕ͔Β͍ͨ΁Μҙຯਂ͍͜ͱͱͯ͠ɺϓϩάϥϛϯάʹڵຯ͕͋Δ͕औΓ૊
    ΜͰ͍ͳ͍ະܦݧऀͷϖϧιφʢސ٬Ϟσϧɺ૝ఆଐੑͷਓ෺૾ͷҙຯʣ͕֫ಘͰ͖ͨ͜ͱ͕ڍ͛Β
    ΕΔɻσʔλͱϖϧιφʹؔͯ͠͸ɺฐࣾ͸શࠃ͔Βདྷࣾ͢Δʮֶߍ๚໰ड͚ೖΕʯΛߦ͍ͬͯͨ͜
    ͱ͕޾͍͠ɺͦͷޙ΋΄΅ಉ৚݅ͷֶशΛ࣮ࢪͯ͠ܧଓతʹ൓ԠΛݟͯ͸ௐ੔͕ܧଓͰ͖ͨɻͬ͘͟
    ΓԆ΂ 100 ਓҎ্ࢼߦͰ͖ͨɻ
    ਤ: αϚʔΩϟϯϓ 2019
    ਤ: اۀ๚໰ϓϩάϥϜ
    48

    View full-size slide

  50. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.5 ໨ඪઃఆͱߦಈࢦ਑
    5.5 ໨ඪઃఆͱߦಈࢦ਑
    a. Πϕϯτޙͷܦա
    ΠϕϯτΛ࣮ࢪͨ͜͠ͱͰۮવ͕Ұͭൃੜͨ͠ɻెาݍʹ͋Δۙྡͷެཱதֶߍͷੜె͕ਃ͠ࠐΜ
    Ͱ͘Εͨ͜ͱ͔ΒىҼ͢Δɻ൴͸ϓϩάϥϛϯάͱΠϕϯτࢀՃʹର͍ͯͨ͠΁Μ೤ҙͱر๬Λ࣋ͬ
    ͍ͯΔֶੜ͕ͩࣄ৘ʹΑΓࢭΉʹࢭ·Εͣܽ੮ͱͳͬͯ͠·ͬͨͱ͍͏ɻ͔͠͠൴͸Ѫ͢΂͖ਓ෺
    ͩͬͨɻչ΍·ΕΔࣄଶʹΑΓ౰࣌ͷڭ৬һ͕୅ΘΓʹݟֶʹདྷࣾ͠ɺςΩετڭࡐΛ࣋ͪؼͬͯษ
    ڧͤͯ͞΋Α͍͔ͱΘ͟Θ֬͟ೝΛٻΊ͖ͯͨͷͰ͋Δɻ΋ͪΖΜঝ୚ͨ͠͏͑Ͱɺઌੜ͸͞Βʹ
    90 ෼ͷϫʔΫγϣοϓΛ͢΂ͯݟֶͯ͠ؼΒΕͨɻͦͷޙ೔ʹઌੜํͱݱঢ়ͷ͓࿩͠Λฉ͍͍ͯ͘
    ͱɺϓϩάϥϛϯάֶश΍ ICT ׆༻ʢ৘ใ୺຤׆༻ʣʹ͸ࢦಋऀ΍ίϯςϯπͷ՝୊͕͋Γɺͦ͠
    ͯੜెʹԿ͕࠷ద͔ͷ໨ॲཱ͕͍ͬͯͳ͍ঢ়گͰ໛ࡧ͍ͯ͠Δঢ়گ͕͏͔͕͍஌Εͨɻͦ͜Ͱಉߍ΁
    ͷϓϩάϥϛϯάֶशࢧԉͱͯ͠ɺ͜ͷϫʔΫγϣοϓΠϕϯτΛϞσϧͱͨ͠ෳ਺ճֶशߨ࠲ͷ࣮
    ݱΛ໨ࢦͯ͠ɺऔΓ૊ΈΛ۩ମԽ͍ͯ͘͜͠ͱʹ྆ऀ߹ҙͨ͠ɻ
    ల։ͱͯ͠͸ґཔऀ͕ೋऀʹͳΔ͕ɺैདྷͷґཔऀͱͯ͠౰ॳΑΓ಺แ͍ͯͨ͠ͱݴͬͯᴥᴪ͸ͳ
    ͘ɺ͋Δ͍͸ґཔऀͷޙΖଆʹҐஔ͢Δɻͭ·Γ૬खଆʹ͓͚Δʮࣗ૊৫ʯͱʮࣗ෼ࣗ਎ʯͷؔ܎ʹ
    ͋ͨΓɺґཔऀͰ͋Δ۠ͱֶߍ͸ʮ౷ׅ૊৫ʯͱʮ૊৫ʯͷؔ܎ʹ͋ͨΔɻΑΓ۩ମతͳ໰୊΁ͷऔ
    Γ૊ΈͱղܾΛҎͯ׆ಈͱ੒ՌΛࣔ͢΄͏͕ΑΓ༗ҙٛͰ͋Δͱߟ͑ɺैདྷͷґཔऀʢґཔऀᶃʣͷ
    ҙࢥͷ΋ͱ۩ମతͳࢪࡦ࣮ࢪઌͱͳΔֶߍʢґཔऀᶄʣ΁ͷɺݸผͷ໰୊ࣄྫΛղܾ͢ΔऔΓ૊Έʹ
    ࢹ఺Λམͱͨ͠ɻ
    b. ࣋ଓతʹୡ੒͢Δߦಈࢦ਑ʹམͱ͠ࠐΉ
    ґཔऀͷ໰୊͸ϫϯΞΫγϣϯ΋͘͠͸ 1 ϓϩμΫτͰ͢΂ͯ͸ղফ͠ͳ͍ɻϓϩδΣΫτ͕։࢝
    ͞ΕΔͱࣗ෼ͷ໨ඪ΍ࠓͷ՝୊͚ͩߟ͑ͯಥ͖ਐΜͰ͠·͍ɺ্௕΍૊৫ͷ໨ඪͱͦΕͯ͠·͏͜ͱ
    ͕ଟ͍ɻ
    ͜͜·Ͱݟ͖ͯͨࡾऀͷʮ5W1Hʯ͸੾ΓޱΛม͑͞ΒʹผͷݟํΛͯ͠ݕ౼ΛਂΊΔɻࠓճͷ
    έʔεʹ͓͚Δґཔऀͷ໰୊ͱ͸ɺओޠ͸େ͖ͳ͘͘Γͷਓͷू·ΓͰ͋Γɺશମ΁ͷ࣋ଓత͔ͭॊ
    ೈͳࢧԉΛඞཁͱ͢Δ΋ͷͰ͋Δɻ͜ͷΑ͏ʹ࣌ؒ࣠ͷ௕͍՝୊ʹରͯ͠औΓ૊Ήͱ͖ʹ͸্ԼϨΠ
    Ϡͷࢹ࠲Λߦ͖͠ɺ࣋ଓతʹୡ੒͠ଓ͚Δʮߦಈࢦ਑ʯͱݸผͷʮ໨ඪઃఆʯΛͦͷ౎౓֬ೝͯ͠औ
    Γ૊Ήɻ
    ܧଓͯ͠໰୊ʹऔΓ૊ΉதͰऴ࢝໨తΛݟࣦΘͣʹ໨తΛ਱ߦ͢ΔͨΊʹ࣍ͷϑϨʔϜϫʔΫΛղ
    આ͍ͨ͠ɻ
    49

    View full-size slide

  51. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.5 ໨ඪઃఆͱߦಈࢦ਑
    c. ߦಈࢦ਑ͱ໨ඪઃఆʹʮOKRʯ
    ໨ඪઃఆʹ͍ͭͯ͸ Google ࣾͳͲͰ΋ಋೖ͞Εͨ OKR ͱ͍͏ϑϨʔϜϫʔΫ͕͋Δɻղઆ͢Δ
    ͱɺObjectives and Key Results ɹͷུͰɺ໨ඪʢObjectivesʣ
    ɺओཁࢦ਑ʢKey Resultsʣͷҙຯ͕
    ͋ΔɻO ͱ KR ͷ 2 ఺Λɺ૊৫શମͰɺϓϩδΣΫτ୯ҐͰɺ୲౰ऀͰɺͱ෼ղͯ͠۩ମతʹ͍ͯ͠
    ͘ɻ֤ϨΠϠͰܭଌՄೳͳ໨ඪͱͯ͠۩ମతʹऔΓ૊Ίͯ࠷ऴ໨ඪ͕ୡ੒Ͱ͖Δͱ͢Δ΋ͷɻ͜ͷ໨
    ඪͷԠ༻͸ɺ૊৫΍্௕͔ΒԼͣ͞ͱ΋ࣗ෼Ͱࢹ࠲Λมཻ͑౓Λ্͛Լ͛ͯ͠໨ඪઃఆ͢ΔͱશମΛ
    ၆ᛌ͠ͳ͕Β۩ମతʹऔΓ૊ΊΔɻྨࣅͷϑϨʔϜϫʔΫʹ͸ʮSMARTʯ΍ʮMBOʯͱ͍ͬͨख
    ๏͕͋Δ͕ɺ͍ͣΕͷ৔߹Ͱ΋্Ґ໨ඪ͔ΒԼҐ໨ඪ΁ͷΑ͏ͳ۩ମԽ΍ KPIʢධՁࢦඪʣ͕ॏཁͱ
    ͞Ε͍ͯΔɻ
    ͜Ε·Ͱड़΂͖ͯͨʮ5W1HʯͷϦετ͸໨ඪʹݴ͍׵͑ͯू໿͢ΔͱԼهͷΑ͏ʹͱ·ͱΊΔ͜
    ͱ͕Ͱ͖Δɻ
    Πϕϯτ·Ͱͷ OKR
    • ґཔऀʹͱͬͯ
    –ʢͲ͜Ͱʣ۠಺ͷٛ຿ڭҭɺ20 ೥౓খֶੜͳͲ΁
    –ʢ͍ͭʣͦͷ࣌఺ͷ࣍೥౓ɻ20 ೥౓͔Βͷॱ࣍ඞमԽʹ޲͚ʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣֶशࢦಋཁྖʹ४ڌ͢Δ࣮ࢪϝχϡʔͷఏࣔΛͯ͠
    –ʢͳʹΛʣٛ຿ڭҭ΁ͷϓϩάϥϛϯάֶशࢧԉΛ͢Δɹʢఆྔ໨ඪʣ
    • ࣗ૊৫ʹͱͬͯ
    –ʢͲ͜Ͱʣதֶߍͷओʹٕज़Պ
    –ʢ͍ͭʣதֶߍ͕ϓϩάϥϛϯάΛ࣮ࢪ͢Δ 2021 ೥౓·Ͱʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣຊདྷͷҙຯͷϓϩάϥϛϯάΛࢦಋ͠
    –ʢͳʹΛʣґཔऀͷ๬ΉࢧԉΛ࣮ࢪ͢Δʢ਺ྔʹఆྔ໨ඪʣ
    • ࣗ෼ࣗ਎ʹͱͬͯ
    –ʢͲ͜ͰʣΠϕϯτԠื͖ͯͨ͠தֶੜ
    –ʢ͍ͭʣ3 ϱ݄ޙͷΠϕϯτ·Ͱʹʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣΑ͍ػձΛಀͣ͞ɺΠϕϯτͰԾઆݕূʹد༩͢ΔσʔλΛͱΓ
    –ʢͳʹΛʣֶߍͰ࣮ࢪֶ͍ͨ͠शࢧԉͷ࠷খ੡඼ߏ੒ʢMVPʣͱΧϦΩϡϥϜҊΛ࡞੒͠
    ֶशΠϕϯτͰσʔλΛͱΔʢఆྔ໨ඪʣ
    ͜ͷΑ͏ʹ্ԼϨΠϠͲ͏͠Ͱͭͳ͕Γͷ͋Δےͷ௨ͬͨ໨ඪͱͳ͍ͬͯΔ͜ͱ͕ಡΈऔΓ΍͢
    ͍ɻ
    ʮ5W1HʯʴЋͰॻ͖ى߲ͨ͜͠໨Ͱ͋Δ͜ͱΛ׆͔ͯ͠ whereɾwhenɾshouldɾwhat Λ࢒͠
    ͓͍ͯͨɻͳ͓ࢹ఺͝ͱʹݟΔ࣌ؒ࣠ʹҧ͍͕͋Γʮࣗ෼ࣗ਎ʯͰ͸Πϕϯτ·Ͱ͕ 1 αΠΫϧͱͳ
    Γɺ౸ୡ஍఺͸࠷ऴཁ݅ୡ੒ʹ·͍͍ͩͨͬͯͳ͍ɻͦͷϑΣʔζ͝ͱʹ࣮ݱ͢Δ͜ͱΛݟग़্͠ͷ
    ͭͳ͕ΓΛอ͍ͬͯΔ͜ͱΛҙࣝ͠ͳ͕Βߦಈ͢Δɻ
    ʮࣗ෼ࣗ਎ʯʹ͓͚Δ୲౰Ϩϕϧͷ໨ඪ͕ 1 ͭ
    ୡ੒͞Εͨޙ͸Ұ্ͭͷϨΠϠ͕ࣔ͢ࢦ਑ͷதʹ͋Δ࣍ͳΔߦಈΛʮࣗ෼ࣗ਎ʯʹ՝͢ɻ
    50

    View full-size slide

  52. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.5 ໨ඪઃఆͱߦಈࢦ਑
    Πϕϯτ͔Β೥౓຤·Ͱͷ OKR
    • ґཔऀᶄʹͱͬͯ
    –ʢͲ͜Ͱʣࣗߍ 1ʙ2 ೥ੜ΁
    –ʢ͍ͭʣ࣮ݱͰ͖͏Δ࣌ظʹʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣ·ͣ͸์՝ޙֶश΍Ϋϥϒ׆ಈͳͲͷ೚ҙࢀՃͰ
    –ʢͳʹΛʣΠϕϯτͰࣔ͞ΕͨΑ͏ͳϓϩάϥϛϯάֶशࢧԉΛ͢Δɹʢఆྔ໨ඪʣ
    • ґཔऀᶃʹͱͬͯ
    – ˞ มΘΒͣ
    –ʢͲ͜Ͱʣ۠಺ͷٛ຿ڭҭɺ20 ೥౓খֶੜͳͲ΁
    –ʢ͍ͭʣͦͷ࣌఺ͷ࣍೥౓ɻ20 ೥౓͔Βͷॱ࣍ඞमԽʹ޲͚ʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣֶशࢦಋཁྖʹ४ڌ͢Δ࣮ࢪϝχϡʔͷఏࣔΛͯ͠
    –ʢͳʹΛʣٛ຿ڭҭ΁ͷϓϩάϥϛϯάֶशࢧԉΛ͢Δɹʢఆྔ໨ඪʣ
    • ࣗ૊৫ʹͱͬͯ
    – ˞ มΘΒͣ
    –ʢͲ͜Ͱʣதֶߍͷओʹٕज़Պ
    –ʢ͍ͭʣதֶߍ͕ϓϩάϥϛϯάΛ࣮ࢪ͢Δ 2021 ೥౓·Ͱʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣຊདྷͷҙຯͷϓϩάϥϛϯάΛࢦಋ͠
    –ʢͳʹΛʣґཔऀͷ๬ΉࢧԉΛ࣮ࢪ͢Δʢ਺ྔʹఆྔ໨ඪʣ
    • ࣗ෼ࣗ਎ʹͱͬͯ
    –ʢͲ͜ͰʣΦϑΟγϟϧʹର৅ߍͷߍ಺Ͱ
    –ʢ͍ͭʣ೥౓಺ͭ·Γ 5 ϱ݄Ҏ಺ʹʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣΑ͍ػձΛಀͣ͞ɺԾઆݕূͱվળػձͱͯ͠ɺ͞Βʹࣄྫͮ͘Γͱͯ͠
    –ʢͳʹΛʣֶߍͰ࣮ࢪ͢΂͖੡඼ߏ੒ͱΧϦΩϡϥϜΛߏ੒ֶ͠शࢧԉ͢Δʢఆྔ໨ඪʣ
    ޙऀͷϦετͰ͸ɺֶߍͰ͋Δʮґཔऀᶄʯ͸ࣗ෼ࣗ਎ͷରہͱͳΔΑ͏࠷্Ґʹܝࡌͨ͠ɻ͜Ε
    ʹΑͬͯؒͷϨΠϠ૊৫ΛͲͷΑ͏ʹҙࣝ͢Δͷ͔͕มΘΓɺ࠷ԼҐ໨ඪୡ੒Ͱ࠷্Ґ໨ඪ՝୊͕ղ
    ܾͰ͖Δ͔ΛٻΊ͍ͯΔɺͱࣔ͢͜ͱʹͳΔɻ
    d. ʮͲ͏΍ͬͯʯ෦෼ɺίϯςϯπͷߏஙʹ޲͚ͯ
    ͦΕͰ͸࣍અ͔Βɺίϯςϯπͷاը։ൃʹ໨Λ޲͚ͯղઆ͢ΔɻΠϕϯτͱͦͷޙʹ͓͍ͯͲͷ
    Α͏ͳઓུ΍ҙਤΛ΋ͬͯൃ૝ɾاը͍͔ͯͬͨ͠ʹ͍ͭͯղઆͦ͠ͷख๏Λ঺հ͍ͨ͠ɻ
    51

    View full-size slide

  53. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.6 ίϯςϯπاըͱ͞·͟·ͳ෼ੳ
    5.6 ίϯςϯπاըͱ͞·͟·ͳ෼ੳ
    ఏڙ͢ΔڭࡐͱΧϦΩϡϥϜʢҎԼίϯςϯπʣʹ͍ͭͯߟ͑Δɻ࣮ݱ͍ͨ͠ཁ݅͸ɺςΩετϓ
    ϩάϥϛϯάͰήʔϛϑΟέʔγϣϯͱֶशͰ͋ΔɻมԽٿΛ౤͍͛ͨ༁Ͱ͸ͳ͍͕ɺط੡඼ͱಉ͡
    ΋ͷΛ࡞ͬͯ΋·ͬͨ͘ҙຯ͕ͳ͍ɻط੡඼ͱಉ͡Α͏ͳͱ͜Ζֶ͕शͰ͖Δ΋ͷͩͱ͢Δͱɺٸ͝
    ͠Β͑ͨͪ͜͠Βʹউͪ໨͕ͳ͍͏͑ɺΦϦδφϧΛར༻ͨ͠΄͏͕ϚγͱͳΔɻ·ͨڭҭۀքͰ
    ͸ɺڭࡐ։ൃձ͕ࣾઐ໳ੑΛ׆͔ͯ͠ൢച͍ͯ͠ΔΩοτ͕ͨ͘͞Μ͋Γɺ͢Ͱʹར༻͍ͯ͠Δ৔߹
    ΋͋ΔɻίϯγϡʔϚʔʢফඅऀʣʹ޲͚ͯ͸ɺήʔϛϑΟέʔγϣϯΛ׆ָ͔ͯ͠͠Έͳ͕Βֶश
    Ͱ͖Δʢ·ͨ͸ֶशͱ͸ޛΒͤͳ͍ʣΞϓϦέʔγϣϯ΍੡඼͕ͨ͘͞Μ͋Δɻاըʹ͋ͨͬͯ͸ɺ
    औΓ૊Ή༨஍͕͋Δͷ͔Ͳ͏͔͔Βௐ΂Δඞཁ͕͋ΔͨΊɺࢢ৔΍ࣗ਎Λ͔ͬ͠ΓݟΔ͜ͱ͔Β࢝
    ΊΔɻ
    a. STP ෼ੳʢࢢ৔λʔήοτϙδγϣϯʣ
    ৽نࣄۀΛల։͢Δ͏͑Ͱࢢ৔ʹ͓͚ΔཱͪҐஔΛ໌֬Խ͢ΔͨΊʹ༻͍ΔɺϑΟϦοϓɾίτ
    ϥʔͷఏএͨ͠ϑϨʔϜϫʔΫͰ͋ΔɻSegmentationʢࢢ৔ࡉ෼Խʣ - Targetingʢࢢ৔બ୒ʣ -
    PositioningʢཱͪҐஔʣɹͷ಄จࣈΛͱͬͯ STP ෼ੳͱ͍͏ɻ୭ʹΉ͚Δͷ͕ద੾͔ɺڝ߹ͱͷ੗
    Έ෼͚͕Ͱ͖Δ͔ʹ͍ͭͯࢹ֮తʹ΋෼ੳͰ͖Δɻ
    ڝ߹ͱઃఆ͍͔ͨͭ͘͠ͷαʔϏε͓Αͼ੡඼Λ੡඼঺հΩϟονίϐʔΛݩʹର৅೥ྸΛ෼ྨ
    ͢Δɻ
    ڝ߹ ༮ࣇ খֶੜʢ௿ʣ খֶੜʢதʣ খֶੜʢߴʣ தֶੜ ߴߍੜ Ұൠ
    ੡඼ V ̋ ̋ - - - - -
    ੡඼ P - ̋ ̋ - - - -
    ੡඼ Q - ̋ ̋ ̋ - - -
    ੡඼ S - ̋ ̋ ̋ - - -
    ੡඼ H - ̋ ̋ ̋ ̋ ̋ ̋
    ੡඼ N - - ̋ ̋ ̋ ̋ ̋
    දͷ੡඼ྫͱͯ͠͸෼͔ΓͮΒ͍͕ɺ༗ྗͳ੡඼͕ौ଺͓ͯ͠Βͣಛ௃͕ଧͪग़͠΍͍͢ྖҬ͕
    ʮதֶɾߴߍʯͱ͍͏λʔήοτԾઆ͕ݟ͑ͨɻಉ༷ͷηάϝϯτʹ͋Δ੡඼ Hɾ੡඼ N ͳͲͷڝ߹
    ͱͷϙδγϣϯͰ͸ɺ
    ʢ౰ॳʣAndroid λϒϨοτΛத৺ʹ͢Δ͜ͱͰϓϥοτϑΥʔϜʹΑΔࠩผ
    ԽΛૂͬͨɻͦͷ΄ֶ͔शྖҬͷॅΈ෼͚ΛධՁ͠ͳ͕Βɺதֶֶशࢦಋཁྖ͕ࣔ͢ʮωοτϫʔ
    Ϋʯͷར༻Λߟྀ͢Δ෦෼͸ྫ͕গͳ͍ɻ·ͨςΩετϓϩάϥϛϯάͷڝ߹Ͱ͸શମతʹυϦϧܗ
    ͕ࣜଟ͍ͨΊɺ׆༻΍ࣗݾ࣮ݱʹͭͳ͛ΔֶशͳͲɺֶशࣗମͷػೳΑΓʮԠ༻ʯʹ΋ࠩผԽ͢Δϙ
    ΠϯτΛஔ͚Δɻ˞ϓϥοτϑΥʔϜʹ͍ͭͯ͸ผهͨ͠௨Γͦͷޙ Windows λϒϨοτ PC ΁ͷ
    ఏڙʹࢸΔ
    52

    View full-size slide

  54. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.6 ίϯςϯπاըͱ͞·͟·ͳ෼ੳ
    b. VRIO ෼ੳʢڝ߹༏Ґੑʣ
    ܦӦࢿݯΛ 4 ͭͷࢹ఺ͰධՁ͠෼ੳ͢ΔͨΊͷɺδΣΠɾBɾόʔχʔ͕ఏএͨ͠ϑϨʔϜϫʔ
    ΫͰ͋Δɻ4 ͭͷࢹ఺͸ɺValueʢܦࡁՁ஋ʣ- Rarityʢرগੑʣ- Inimitability ʢ໛฿ࠔ೉ੑʣ-
    Organizationʢ૊৫ʣ
    ɻ
    • ܦࡁՁ஋ɹ ... ސ٬΍ࣾձʹͱͬͯՁ஋͕͋Δ͔
    • رɹগɹੑ ... رগੑ͕͋ͬͯಛ௃෇͚ΒΕΔ͔
    • ໛฿ࠔ೉ੑ ... ྨࣅ඼͕؆୯ʹग़ճͬͯ͠·͏͔
    • ૊ɹɹ৫ɹ ... ׆༻Ͱ͖Δ૊৫ʹͳ͍ͬͯΔ͔
    ֶࣗࣾशίϯςϯπͷ VRIO ෼ੳ
    • ܦࡁՁ஋
    – ؆୯ͰςΩετϓϩάϥϛϯάͰͪΐ͏ͲΑ͍΋ͷ͕গͳ͍தͰόϦΤʔγϣϯΛ࣋ͨͤ
    ֶͨͼ͕֫ಘͰ͖ΔͨΊࢦಋ΋ؚΉύοέʔδʹର͢ΔՁ஋ͱͯ͠ଧͪग़ͤΔ
    • رগੑ
    – ςΩετϓϩάϥϛϯάίϯςϯπɺήʔϛϑΟέʔγϣϯ՝୊ֶशɺςΩετϓϩάϥ
    ϛϯάͷࣗ༝౓͕࣋ͭόϥΤςΟɺࣾһ͕௚઀ࢦಋɺͷֻ͚ࢉʹرগੑ͕͋Δ
    • ໛฿ࠔ೉ੑ
    – ιϑτ΢ΣΞɾΧϦΩϡϥϜɾࢦಋɾԠ༻ͷཁૉ͕͋Γ࣮ݱίετ͕ൺֱతߴ͍
    – ฐࣾͷεϚʔτϑΥϯΞϓϦʮϞϯελʔετϥΠΫʯʹొ৔͢ΔਓؾΩϟϥΫλʔʮΦ
    ϥΰϯʯ͕׆༻͞Ε͓ͯΓɺֶशʹର͢ΔোนΛݮΒ͠ಠࣗੑɾݸੑ͕ߴ·͍ͬͯΔ
    • ૊৫
    – ͜ͷྖҬʹ͓͍͔ͯͳΓͷࡋྔΛ΋ͬͯ΄ͱΜͲࣗ༝ʹͤͯ͞΋Β͍͑ͯΔͨΊɺ࡞ͬͨ
    ίϯςϯπΛ׆༻͠ల։͢ΔͨΊʹ·ͨ׆ಈͦ͠ΕͧΕΛ݁ͼ෇͚Δ͜ͱ͕Ͱ͖Δɻ
    ʢࠓ
    ճͷࣥච΋ͦͷҰ؀Ͱ͋Δʣ
    ΑΓΑ͍෼ੳͱ݁ՌΛ׆͔͢૊৫ʹ
    VRIO ෼ੳΛཧղͨ͠͏͑ͰϓϩδΣΫτ਱ߦ͍ͯ͠ΔͷͰ͋Ε͹ɺͦͷϓϩμΫτʢ੡඼ͱαʔ
    ϏεΛؚΉʣ͕༗ҙٛͰ͋Δͷ͔ɺ͋Δ͍͸ΑΓྑ͘ΑΓ͍҆΋ͷ͕͢Ͱʹଘࡏͨ͠Γ͙͢ग़ճͬͯ
    ͠·͏ͷ͔ΛݟΔ͜ͱ͕Ͱ͖Δɻڝ߹༏Ґੑ΍ݸੑʢྑ͞ʣΛཧղͨ͠͏͑Ͱίϯςϯπ։ൃ͔Βఏ
    ࣔ·Ͱ͕ߦ͑ΔͷͰ͋Ε͹ɺ୯ʹ෺௝͍͔͠Βɺײ৘Ҡೖ͍ͯ͠Δ͔Βɺͱ͍ͬͨओ؍తͳηʔϧε
    ϙΠϯτʹྗΛೖΕͯޡͬͨૌٻΛͯ͠͠·͏Մೳੑ͕ݮΔͩΖ͏ɻ
    ݁࿦Λม͑ΒΕͳ͍૊৫͕෼ੳΛ͢Δ͜ͱҎ্ʹແՁ஋ͳ΋ͷ͸ͳ͍ɻաڈܦݧͨ͠ଟ͘ͷϓϩμ
    ΫτͰ͸ϏδωεϩδοΫ΍खஈͷબఆ͕ઌʹ͋ΓͦͷؒΛίϯςϯπاըͰຒΊ͍ͯΔɻVRIO ෼
    ੳͷ؍఺΍ͦͷ΄͔ͷ༗ޮͳ෼ੳͰ༏Ґੑ΍Ձ஋͕ࣔͤͳ͍ͷͰ͋Ε͹ɺͰ͖Δ͚ͩૣ͍λΠϛϯά
    ͰͷʮϐϘοτʯΛɺͭ·Γย଍ΛͣΒ͢มֵ͕๬·ΕΔɻ
    53

    View full-size slide

  55. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    a. ϑϨʔϜϫʔΫʮϦʔϯΩϟϯόεʯͰߟ͑Δ
    ىۀɾࣄۀΞΠσΞΛՄࢹԽͯ͠ɺݕূ͠վળ͢Δ͏͑Ͱ໾ʹཱͭߟ͑ํͷҰͭɻͦͷத͔Βɺί
    ετ΍ऩӹɺ΄΅֬ఆ͍ͯ͠Δྲྀ௨νϟϯωϧͳͲΛল͖ͳ͕ΒԼهʹݶఆ͢Δͱࠓճ͸ධՁ߲໨ͱ
    ͯ͠ར༻͠΍͍͢ɻ
    1. ސ٬ͷ՝୊
    2. ސ٬ηάϝϯτ
    3. Ձ஋
    4. ιϦϡʔγϣϯ
    5. ༏Ґੑ
    ʮϦʔϯΩϟϯόεʯ΍ͦͷલ਎Ͱ͋ΔʮϏδωϧϞσϧδΣωϨʔγϣϯϚοϓʯͰ͸ɺ͜ΕΒ
    ΛؚΉ 9 ߲΄ͲΛϚτϦοΫεతͳදʹͯ͠Ծઆݕূ͠ෳ਺Ҋ͔Β༗ޮͳ΋ͷΛऔࣺબ୒͍ͯ͠Δɻ
    ਤʹͤͣͱ΋͜ͷπʔϧ͸ػೳ͠ߟ͑ํͷπʔϧͱͯ͠·͞ʹʮ໰୊ղܾʯͷΞϓϩʔνͦͷ΋ͷͱ
    ͯ͠ݟΔ͜ͱ͕Ͱ͖Δɻ
    ਤ: Ωϟϯόεͷྫ
    ڭҭࢧԉͷՁ஋ͱιϦϡʔγϣϯ
    ࣗࣾίϯςϯπΛ౰ͯ͸Ίͯߏ૝͢Δͱ...
    • ސ٬ͷ՝୊
    –ʢͲ͜Ͱʣ۠಺ͷٛ຿ڭҭɺ20 ೥౓খֶੜͳͲ΁
    –ʢ͍ͭʣͦͷ࣌఺ͷ࣍೥౓ɻ20 ೥౓͔ΒͷඞमԽʹ޲͚ʢظ೔໨ඪʣ
    –ʢͲ͏͢΂͖ʣֶशࢦಋཁྖʹ४ڌ͢Δ࣮ࢪϝχϡʔͷఏࣔΛͯ͠
    –ʢͳʹΛʣٛ຿ڭҭ΁ͷϓϩάϥϛϯάֶशࢧԉΛ͢Δɹʢఆྔ໨ඪʣ
    • ސ٬ηάϝϯτ
    –ʢͲ͜Ͱʣதֶߍͷओʹٕज़Պ
    54

    View full-size slide

  56. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    • Ձ஋
    – ະܦݧऀ͕ςΩετϓϩάϥϛϯάΛ͍͖ͳΓମݧͰ͖Δ
    – ΤϯδχΞ͕ߨࢣʹདྷΔ
    – ϢχʔΫͳڭࡐͰָ͠Έͳ͕ΒֶशͰ͖Δ
    • ιϦϡʔγϣϯ
    – ςΩετϓϩάϥϛϯάΛଧͪࠐΜͰࢼͤΔ
    – ଧͪࠐ·ͳͯ͘΋ςΩετϓϩάϥϛϯάֶ͕΂Δ
    – ϓϩάϥϛϯάͷυϦϧֶश͕Ͱ͖Δ
    – ࡞඼੍࡞΍ڭՊ΁ͷԠ༻ʹΑͬͯϓϩάϥϛϯάࣗମ͕πʔϧʹͳΔ
    • ༏Ґੑ
    – ॳΊ͔ΒதֶΛϝΠϯλʔήοτʹ͍ͯ͠ΔͨΊҰఆͷద߹ੑ͕͋Δ
    – ήʔϜͱαʔϏεͷձࣾΒָ͍͠͠·ͤํ͕͋Δ
    – ֶशͷόϦΤʔγϣϯ΍δϟϯϧ෯͕ͱΕΔ
    • ظݶ͕͋ΔதͰιϑτ΢ΣΞʹԿΛඋ͑ఏڙͰ͖Δ͔ͷج४͸...
    – ϦʔϯελʔτΞοϓͷ MVPʢՁ஋ఏڙ࠷খ੡඼ʣΛ࣠ʹඞཁͳ΋ͷ͔Β࣌ؒͷݶΓʹ
    ࣮ݱ͢Δ
    ∗ Կ͕ MVP ͱͳΔ͔͸ 5W1H ΍ OKR ͷ্͔ΒԼ·Ͱͷͭͳ͕Γ͔Β͔ͭΉ
    – UVPʢಠࣗͷՁ஋ఏҊʣ։ൃ͕࣮ݱͰ͖ͨ͜ͱͰ࣮֬ʹιϑτ΢ΣΞ͕ఏڙͰ͖Δཪ෇
    ͚ʹͳΔ
    ∗ पΓͷػೳ͸ͳΜͱͰ΋ͳΓɺ࠷௿Ͱ΋උ͑ͯͳͯ͘΋໨తࣗମ͸ୡ੒Ͱ͖Δ
    ਖ਼͍͠ݕ౼ͷॱংͰߏ૝͢Δ
    ஫ҙ͓ͯ͘͠෦෼ͱͯ͠ʮιϦϡʔγϣϯʯͭ·Γ੡඼͕࣮ݱ͢ΔػೳΛ΋͔ͬͯͳ͑Δ෦෼͸ 9
    ߲໨ͷ͏ͪͷ 1 ͭͰ͔͠ͳ͘ɺ
    ʮ੡඼ΞΠσΞʹറΒΕ͗͢Δͳʯͱ͍͏ϝοηʔδ͕ͦ͜ʹ͋Δͱ
    ͍͏͜ͱͩͦ͏ͩɻՁ஋΍ιϦϡʔγϣϯʹ͸ϦʔϯελʔτΞοϓͷ MVPʢՁ஋ఏڙ࠷খ੡඼ʣ
    ͔Β࣮ݱͯ͠ݕূ͢Δ͜ͱ͕ॏཁͰ͋Δͱड़΂ΒΕ͍ͯΔɻ·ͨ MVP ͷ৺ଁ෦ɺͭ·Γ UVPʢಠ
    ࣗͷՁ஋ఏҊʣ͕ڝ߹༏Ґੑʹͭͳ͕ΓͦͷαʔϏεΛಛ௃͚ͮΔͱ͍͏ɻ
    Ωϟϯόεʹ౰ͯ͸Ίͳ͕Βߏ૝ͱݕূΛߦ͖དྷ͢Ε͹ɺม͑Δ΂͖Օॴ͕ɺૌٻ͢ΔʮՁ஋ʯͦ
    ͷ΋ͷͳͷ͔۩ݱԽ͢ΔʮιϦϡʔγϣϯʯͳͷ͔͕໌֬ʹ೺ѲͰ͖Δɻߟ͕͑ٴ͹ͣʹ͋Ε͜Εม
    ͍͑ͯΔͱ͖ͦΕ͸ʮιϦϡʔγϣϯʯͭ·Γ۩ମతͳखஈΛม͍͑ͯΔ͚ͩͰՁ஋͕มΘ͍ͬͯͳ
    ͍Մೳੑ͕͋ΔͩΖ͏ɻਖ਼͍͠ೝࣝͷʮ՝୊ʯͱʮސ٬ʯͷؒʹͦͷʮՁ஋ʯ͕ఆٛͰ͖͍ͯΔ͔ɺ
    ݕ౼ͷॱং͸·ͨॏཁͳҙຯΛ࣋ͭɻ
    55

    View full-size slide

  57. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    b. ໰୊ղܾΞϓϩʔνͱͯ͠ͷʮσβΠϯࢥߟʯ
    σβΠϯࢥߟ͸໰୊ղܾͷϑϨʔϜϫʔΫͷҰͭͰɺ΋ͱ΋ͱσβΠφʔͰ༻͍ΒΕΔࢥߟ๏ͰԾ
    આͱݕূʹΑͬͯݚຏ͍ͯ͘͠औΓ૊ΈํʹϏδωεͷ՝୊ղܾͱͷڞ௨఺͕͋Δɻࢥߟͷํ๏͸࣍
    ͷͱ͓Γɻ
    • ڞɹײɹɹɹ ... ৘ใऩू΍ֶशɺϢʔβʔͱڞײ͢Δ
    • ఆɹٛɹɹɹ ... Ϣʔβʔͷؾ࣋ͪͰ໰୊ʹؾ෇͘ɺ෼ੳ͠໰୊ఆٛ͢Δ
    • ૑ɹ଄ɹɹɹ ... ໰୊ΛղܾͰ͖ΔΞΠσΞΛ͍͔ͭ͘૑଄͠ڍ͛Δ
    • ϓϩτλΠϓ ... ΞΠσΞ͕࣮ࡍʹࢼͤΔΑ͏ʹࢼ࡞͢Δ
    • ςετɹɹɹ ... ࢼ࡞ͨ͠੡඼Λ࣮ࡍʹςετ͠ධՁ͢Δ
    ੡඼։ൃͷϑΣʔζ͕σβΠϯࢥߟΛదԠ͠΍͍͢ɻڭࡐιϑτ΢ΣΞ։ൃ࣌ʹ͜ͷࢥߟΛ౰ͯ͸
    ΊͨྫΛڍ͛Δɻ
    • ڞײ
    – ίϯϐϡʔλૢ࡞ͦͷ΋ͷ΋ॳ৺ऀֶ͕ͩशͷຊ࣭Ͱ͸ͳ͘ϓϩάϥϛϯάΛֶͼ͍ͨ
    • ఆٛ
    – ॳ৺ऀͳͷͰΩʔϘʔυೖྗͳΜͯͯͨ͠Β೔͕฻Εͯ͠·͏͠໘౗ʹͳΔ
    • ૑଄
    – จࣈೖྗΛͤͣೖྗ͢ΔԿΒ͔ͷػೳ͕͋Ε͹ମݧͱֶशʹूதͰ͖Δ
    • ϓϩτλΠϓ
    – ίʔυૠೖϘλϯͷ࡞੒
    • ςετ
    – ݕূͰλΠϐϯάෆಘखͰ΋ίʔυૠೖػೳͰετϨεͳ͘΍Γ͖Εͨʢߠఆʣ
    – ߦͱΠϯσϯτ΍ϒϩοΫʹ͍ͭͯͷཧղෆ଍ʹΑΓೖྗϛε͕ى͜Δʢվળʣ
    ͜ͷݕূͱͦͷޙͷ࣮ݱʹΑͬͯதֶ 1 ೥ͳͲλΠϐϯάෆಘखͷֶੜ΁͸΋ͪΖΜͷ͜ͱখֶੜ
    Ͱ͋ͬͯ΋ར༻Ͱ͖Δɻґཔऀ͔Β΋খֶߍͰͷར༻Λͯ͠΋Α͍Μ͡Όͳ͍͔ͱظ଴͕͕͋ͬͨɺ
    ݱ࣌఺Ͱ͸খֶੜ΁ͷࢦಋͦͷ΋ͷͷ೉͕͋͠͞ΔͨΊԕྀ͍ͯ͠Δঢ়گͰ͋Δɻͳ͓զ͕Ոͷখ 1
    ʢ౰࣌ʣͷ່͕ͳΜͱ͔ΫϦΞ͍ͯͨ͠ɻ
    56

    View full-size slide

  58. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    ਤ: ϓϩάϥϛϯάମݧߨ࠲
    57

    View full-size slide

  59. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    c. ৽͍͠ΞϓϩʔνʮετʔϦʔࢥߟʯͰ੾Γ։͘
    ͦ͏͜͏ΞϓϩʔνΛߟ͑ͳ͕ΒऔΓ૊ΜͰ͍Δ͏ͪ໰୊ղܾͷاըͱ࿩ͷ௨͠ํʹ΋ίπ͕͔ͭ
    Ίͯ͘Δɻ͓·͚ͱͯۙ͠گͰࢲ͕࣮ફ͍ͯ͠Δߟ͑ํͷҰͭʮετʔϦʔࢥߟʯͳΔ΋ͷΛ঺հ͠
    ͓͖͍ͯͨɻࢥߟ͸ΦϦδφϧͰ͋Γݺশ͸͜͜Ͱͷղઆ༻ʹ෇͚͍ͯΔ͚ͩͰ࿦จ͕͋Δ΋ͷͰ͸
    ͳ͍͕ɺ༗ޮͳہ໘͕͔ͳΓଟ͋͘Δͱߟ͍͑ͯΔɻ
    • ސ٬ͷཧ૝ΛݟΔ
    – ސ٬ͷ੠Λฉ͖৘ใΛऩू࣮͠ݱ͍ͨ͠ͶΒ͍ͱͦͷഎܠΛݟΔ
    ∗ʢ࣮ྫʣ์՝ޙֶशΑΓٕज़Պͷतۀࢧԉ͕ཉ͍͠ɺΑΓೝ஌ͷ͋ΔݴޠΛֶ͹ͤͨ
    ͍ɺPTA ͷҙݟ΋ټΈ͍ͨɺཧ਺ڭҭͰઌߦ͍ͨ͠ɺઐ໳ڭ་͕গͳ͘ରԠͰ͖ͳ͍
    • ϓϩοτΛ࡞Δ
    – ےಓʹ߅͑ͳ͍τϐοΫͱΩʔϫʔυͰετʔϦʔΛଧཱͪͯΔ
    ∗ʢ࣮ྫʣٕज़Պ৘ใͱͯ͠ɾߴߍͰ͞Βʹߴ౓Խ͢Δ৘ใֶशʹඋ͑ͯɾ৬ۀʹͰ͖
    ͯ͜Ε͔Βֶͼ͍ͨςΩετϓϩάϥϛϯάݴޠ No1 ͷ Python ݴޠΛɾ४උͱૢ
    ࡞ͷख͕͔͔ؒΒͳ͍ΦϦδφϧΞϓϦΛ͔ͭͬͯɾઐ໳ߨࢣ͔Βख୹ʹڭΘΓɾϓ
    ϩάϥϛϯάͰ࡞඼੍࡞͕Ͱ͖ΔΑ͏ʹͳΔ·Ͱͷઌߦֶͨ͠शΛɾਪਐֶ͍ͨ͠ߍ
    ͷڭ་ʹΈ͍͍ͯͨͩͯतۀઃܭ࣮͠ࢪ͢Δͱɾٕज़Պڭ་͕औΓ૊Μͩ΋ͷͰ࣮ࢪ
    ྫ͕͋ΔͨΊ۠಺શߍ΁ͷల։͕ಉ೥଎΍͔ʹͰ͖Δɻ
    • ੣࣮ʹ GIVE ͢Δ
    –ʮGIVEʯ͸ॻ੶ʮGIVE ˍ TAKEʯʹ΋ొ৔͢ΔߦಈಛੑͰଞऀ΁༩͑ΔߦಈΛࣔ͢
    – ϓϩοτҎ্ͷڻ͖Λ༩͑Δ࡞඼ʢ੡඼ʣΛ੣࣮ʹࣔ͠ސ٬΁ GIVE Λି͚ͭ͠ Funʢຯ
    ํʣʹม͑Δ
    ∗ʢ࣮ྫʣεέδϡʔϧతʹΏͱΓΛ࣋ͬͯܦաͷ಺༰Λ։ࣔͯ͠ɺ֬ೝऀ͸໔Ӹ͕ͳ
    ͍Ώ͑ιϑτ΢ΣΞෆ۩߹͸θϩͰ͋Γଓ͚ɺ͔Ώ͍ͱ͜Ζʹख͕ಧ͖؆୯͕͞ࡍཱ
    ͭΑ͏ʹ͠ɺࢹ֮తʹڻ͖͕͋ΔίϯςϯπΛؚΈɺ੡඼ͱ಺༰ͷઐ໳ՈͰ͋Δ͜ͱ
    Λࣔ͠ɺސ٬ͷݸਓతͳ஌త޷ح৺ʹ͔͑ͬ͞͠Γ޲͖߹͏ɻ
    • ஄Έंʹ৐Δ
    –ʮ஄Έंʯ͸ॻ੶ʮϏδϣφϦʔΧϯύχʔʯʹ΋ొ৔͢Δ
    – ࢿݯͱ࣌ؒ͸༗ݶͳͷͰߦಈ͸ඞͣೋ࣍ࡾ࣍ར༻Λલఏʹաڈͱະདྷʹͭͳ͛Δετʔ
    ϦʔΛඳ͘
    – ෳ਺ͷސ٬ͷ໰୊ղܾΛ 1 ΞΫγϣϯͰຬͨͦ͠ͷઐ໳ՈʹͳΔ
    ∗ʢ࣮ྫʣ
    ʮֶशΠϕϯτʯͰಋೖͨ͠ϏΪφʔ޲͚ςΩετϓϩάϥϛϯάମݧιϑτ
    ʢLua ݴޠʣΛస༻͠ʮٕज़Պʯͷ Python ֶशʹਐԽɻͦͷޙ੡඼ͱΧϦΩϡϥϜ
    ͸స༻͠ʮ෦׆ʯͷΑΓߴ౓ͳ࣮ફʹ΋׆͔͓ͤͯΓ૬৐ޮՌͰ΋ͱ΋ͱͷίϯςϯ
    πͱͱ΋ʹൃలͨ͠ɻࠓޙ͞Βʹผतۀͷ஫໨ίϯςϯπʹస༻͠׆͔͢΂͘४උ͠
    ͍ͯΔɻ
    58

    View full-size slide

  60. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.7 ΞΠσΞͷൃ૝ͱࢥߟ
    ਤ: Python ֶशը໘
    59

    View full-size slide

  61. ୈ 5 ষ ֶߍఏڙιϑτ΢ΣΞͰ໰୊ղܾ 5.8 ࠷ޙʹ
    5.8 ࠷ޙʹ
    ϑϨʔϜϫʔΫ΍πʔϧ͸ڍ͛ͨҎ֎΋ͨ͘͞Μ͋Δ͕ɺࠓճͷ΋ͷ͚ͩͰ΋ଟ͘ײ͡ɺͳ͓͔ͭ
    ؔ࿈͢ΔͲ͏͠͸ͲΕ΋ڞ௨఺͕͋Δɻ΋͸΍Ұॹʹࢥ͖͑ͯͨͷ͸͖ͬͱࢲ͚ͩͰ͸ͳ͍͕ɺٯʹ
    ͦ͏͍͏΋ͷͩͱࢥ͍ͬͯΔɻ఻͍͑ͨͷ͸ɺ͜ΕΒΛ͍͘Β஌͍ͬͯͯ΋ɺීஈ͔Βࣗવʹ׆༻Ͱ
    ͖͍ͯΔࢥߟ͕਎ʹ͍͍ͭͯͳ͚Ε͹ҙຯ͸ͳ͍ɻϓϨΠϠʔʢݱ৔ʣ͸ࣗ෼ͷྖҬͰ࠷େݶ׆༂͠
    ࣗݾ࣮ݱͨ͘͠ͳΔͷ͸ੑʢ͕͞ʣͰ͋ΓͦΕ͸߅͑ͳ͍ɻ௕͘ଟ͘ͷΤωϧΪʔΛ஫͍Ͱ͜ͱʹऔ
    Γ૊Ήͱ͖ɺͦͷʮιϦϡʔγϣϯʯͷपΓΛΑ͘ݟఆΊΔ͜ͱ͕େ੾Ͱ͋Γ͢΂ͯͷࢿݯ͸༗ݶͳ
    ͷͩɻޘָ΋ɺੜ׆΋ɺڭҭ΋ɺ໰୊ͱղܾͷ͍ͣΕ͔ͷதʹ͋Δɻͦ͜ʹ͸ɺ໰୊ղܾʹࢸΒ͠Ί
    Δ࿦ཧతͳશମܭը͸͋Δͷ͔ɺͦͷιϦϡʔγϣϯ͸ MVP ͔ͦΕҎ֎͔ɺ՝୊ͱސ٬Ձ஋·ͨ͸
    ໰୊ఆٛͱԾઆઃఆ͞Ε͍ͯΔ͔ɺͦͷԾઆ͸ݕূͰ͖͍ͯΔͷ͔ʔɻ
    Appendix
    ᶗ. ՝୊ղܾܕֶशʙPBLʢProject-Based-Leaningʣ
    ষ຤ʹɺ໰୊ղܾʹྨࣅؔ͠࿈ͨ͠ςʔϚͰ͋Δʮ՝୊ղܾܕֶशʯ
    *3ͱ͍͏ֶशख๏͕ڭҭքͰ
    ೐Θ͍ͬͯΔͨΊ঺հ͢Δɻӳޠදه͸ PBLʢProject-Based-Leaningʣͱݴ͍ۙ೥஫໨͞Εॏࢹ͞
    Εͭͭ͋Δɻֶੜ͕ͨͪ՝୊Λղܾ͢ΔͨΊͷྗΛཆ͏ͨΊͷֶशํ๏ʹΑΓɺॊೈͳࢥߟྗ΍Ԡ༻
    ྗΛ਎ʹ͚ͭ׆༂Ͱ͖Δਓ෺Λ͸͙͘Ήૂ͍͕͋Δɻֶੜ͕՝୊ΛࣗΒൃݟ͠ඞཁͳ͜ͱΛࣗΒֶͿ
    ͜ͱͰɺΧϦΩϡϥϜܕͷֶशʹൺ΂ΑΓॊೈͳࢥߟ͕਎ʹ͖ͭೳྗ͕৳͹ͤΔͱ͍͏΋ͷɻւ֎Ͱ
    ͸ΧϦΩϡϥϜͳ͘͢΂ͯ PBL ʹͳ͍ͬͯΔֶߍ΋͋Δͱ͍͏͕ɺࠃ಺Ͱ΋ڭՊΧϦΩϡϥϜͱ͸
    ผʹฒߦͯ͠೥ؒΛ௨ͯ͠ܧଓతʹऔΓ૊ΜͰ͍Δֶߍͷࣄྫ΋͋ΔɻPBL Ͱ͸άϧʔϓϫʔΫͰ
    औΓ૊ΈɺνʔϜ֎΁ͷൃද·Ͱ͕ඞؚͣ·ΕΔɻऔΓ૊Έํ๏͸ओʹ࣍ͷ௨Γɻ
    • ৘ใऩू ... ओ୊ʹؔ࿈͢Δ৘ใΛऩू͢Δ
    • ໰୊ൃݟ ... ໰୊఺Λݟग़͢
    • Ծઆઃఆ ... ݪҼͱղܾํ๏ͷԾઆΛཱͯΔ
    • ݕɹূɹ ... ԾઆΛݕূ͠༗ޮͳରࡦΛൃݟ͢Δ
    • ൃɹදɹ ... ௐࠪͨ͠಺༰ͱ݁ՌΛൃද͢Δ
    ᶘ. MIXI ͷॻ੶ߪೖࢧԉ
    ΤϯδχΞͰ΋Ϗδωε৬Ͱ΋όοΫΦϑΟεͰ΋ɺϚʔέςΟϯάͱϏδωεͷجૅ஌ࣝ͸ಇ͘
    ࣾձਓʹͱͬͯॏཁͳཁૉͩɻMIXI ͷࣾһʹ͸ɺձ͔ࣾΒ͋Γ͕͍ͨࢧԉ͕͋Γʮॻ੶ߪೖࢧԉʯ
    ੍౓ͳΔ΋ͷʹΑͬͯۀ຿΍ࣗݾֶशʹͭͳ͕Δॻ੶ͷߪೖͷඅ༻Λຖ݄ 5500 ԁʢ੫ࠐʣ·Ͱิॿ
    ͯ͘͠ΕΔɻචऀ͸தݹॻ੶Λத৺ʹ೥ؒ 7~80 ࡭ۙ͘ࢧԉͯ͠΋Β͓ͬͯΓɺීஈͷંি΍اըʹ
    ௚઀ؐݩ͍ͯ͠Δɻॻ੶ߪೖࢧԉʹ͍ͭͯ͸Ұ౓͸Ξ΢τϓοτ͍ͨ͠ͱࢥ͍ͬͯͨɻ
    *3 ʮ՝୊ղܾܕʯͷ΄͔ɺઃఆͷҧ͍ʹΑΓʮ໰୊ղܾܕʯ
    ɺ
    ʮ՝୊ୡ੒ܕʯͱ΋͍͏
    60

    View full-size slide

  62. ୈ 6 ষ
    BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳ
    ࢢ۠ொଜ൑ఆ
    ຊߘͰ͸ɺҢ౓ɾܦ౓Ͱදݱ͞Εͨ࠲ඪ͕ɺͲͷ౎ಓ෎ݝɾࢢ۠ொଜʹଘࡏ͢Δͷ͔ɺBigQuery ্
    Ͱ൑ఆ͢Δ͜ͱΛ໨తͱ͍ͯ͠·͢ɻ௨ৗ͸ PostGIS ޓ׵ͷ GIS ؔ਺Ͱ͋Δ ST_CONTAINS ؔ਺*1
    Λ༻͍·͕͢ɺҐஔ৘ใΛӳ਺ࣈͰදݱͨ͠ GeoHash Λ༻͍ͯ୯७ͳจࣈྻҰகͰ൑ఆ͠ɺߴ଎Խ
    ΛਤΓ·͢ɻࠃ౔ަ௨লͷڥքσʔλΛऔಘɾ੔ܗͯ͠ BigQuery ʹऔΓࠐΈɺͲͷΑ͏ʹ GeoHash
    දݱʹม׵͢Δ͔ΛɺຊߘͰ͸ओ୊ͱͯ͠ѻ͍·͢ɻ౎ಓ෎ݝɾࢢ۠ொଜʹݶΒͣɺڥքσʔλ͞
    ͑͋Ε͹ద༻ՄೳͰ͢ɻ1 ԯߦͷσʔλʹର͢Δ࣮ݧͰ͸ɺ௨ৗͷํ๏Ͱ͸ 1 ෼ఔ౓͔͔Δͱ͜Ζɺ
    GeoHash Λ༻͍Δͱ໿ 98% ͷਫ਼౓Λอͪ਺ඵͰ׬ྃ͢Δ͜ͱΛࣔ͠·ͨ͠ɻ
    GeoHash ͱࢢ۠ொଜͷରԠΛࣔ͢ςʔϒϧ͸ɺޙड़͢Δ query_1_3.sqlɺquery_2_3.sqlɺ
    query_3_3.sql Λ݁߹͢ΔͱಘΒΕ·͢ɻ࣮ࡍͷ࢖͍ํ͸ʮGeoHash Λ༻͍ͨํ๏.sqlʯΛࢀߟʹ
    ͯ͠Έ͍ͯͩ͘͞ɻ
    6.1 ͸͡Ίʹ
    εϚʔτϑΥϯͷීٴʹΑΓҐஔ৘ใͷऔಘ͕਎ۙʹͳ͍ͬͯ·͢ɻҐஔ৘ใΛऩू͢Δࡍɺଟ͘
    ͷ৔߹͸Ң౓ͱܦ౓͕஝ੵ͞Ε·͕͢ɺΘ͔Γ΍͍͢΋ͷͰ͸͋Γ·ͤΜɻೃછΈͷ͋Δʮ౎ಓ෎
    ݝɾࢢ۠ொଜʯ͝ͱʹେࡶ೺ʹͰ΋೺ѲͰ͖Ε͹ɺͱࢥͬͨ͜ͱ͕ଟ͍ͷͰ͸ͳ͍ͷͰ͠ΐ͏͔ɻຊ
    ߘͰ঺հ͢Δख๏͸ɺBigQuery ʹ஝ੵ͞Εͨେྔͷσʔλʹରͯ͠ɺ͋Δఔ౓ͷਫ਼౓Ͱߴ଎ʹࢢ۠
    ொଜ͝ͱͷ෼ྨΛࢼΈΔͨΊͷख๏Ͱ͢ɻ
    ຊઅͰ͸ɺجຊతͳ஌ࣝʹ͍ͭͯղઆ͠·͢ɻ
    *1 BigQuery ஍ ཧ ؔ ਺ ͷ Ϧ ϑ Ν Ϩ ϯ ε: https://cloud.google.com/bigquery/docs/reference/standard-
    sql/geography_functions?hl=ja#st_contains
    61

    View full-size slide

  63. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.1 ͸͡Ίʹ
    δΦίʔσΟϯάͱ͸
    δΦίʔσΟϯάͱ͸ɺ
    ʮ౦ژ౎ौ୩۠ 2 ஸ໨ 24-12ʯͷΑ͏ͳॅॴΛ஍ཧ࠲ඪʢҢ౓ܦ౓ͳͲʣʹ
    ม׵͢Δ͜ͱΛࢦ͠·͢ɻҢ౓ܦ౓͚ͩͰ͸ͳ͘ɺ͞·͟·ͳද͠ํ͕͋Γ·͢ɻ·ͨɺҢ౓ܦ౓ͷ
    Α͏ͳҰ఺Λද͢͜ͱ΋͋Ε͹ɺ௕ํܗͳͲͷྖҬΛද͢͜ͱ΋͋Γ·͢ɻ
    ද 6.1: ͍Ζ͍ΖͳδΦίʔσΟϯά
    छྨ ༻ྫ
    ौ୩εΫϥϯϒϧεΫΤΞ
    ʢ1m ఔ౓ͷਫ਼౓ʣ
    ौ୩εΫϥϯϒϧεΫΤΞ
    ʢ1km ఔ౓ͷਫ਼౓ʣ
    Ң౓ɾܦ౓ Ұൠʹ޿͘༻͍ΒΕΔ 35.65840 N,139.70219 E 35.65 N,139.70 E
    GeoHash ଟ͘ͷ Web αʔϏεͳͲ xn76g52j0z xn76g5
    MGRS ཮্ࣗӴୂͳͲ 54SUE8252546836 54SUE8246
    ஍Ҭϝογϡ ੓෎౷ܭͳͲ 5339-3596-1-1-2(125m ਫ਼౓) 5339-3596
    PlusCode*2 Google Maps ͳͲ 8Q7XMP52+9V82 8Q7XMP52+(300m ਫ਼౓)
    QuadKey Azure ͳͲ 133002112303102222000001 13300211230310
    S2 ϙέϞϯ Go ͳͲ 6924437637984796672 6924437654335389696
    GeoHex υϥΫΤ΢ΥʔΫͳͲ XM488542752402 XM4885427
    GeoHash
    GeoHash ͸Ң౓ɾܦ౓Λ Base32 Ͱදݱͨ͠δΦίʔσΟϯάͰ͢ɻgeohash.org ͱ͍͏ Web
    αʔϏεͰߟҊ͞ΕɺύϒϦοΫυϝΠϯͱͳ͍ͬͯ·͢ɻGeoHash ͸Ң౓ͱܦ౓ͷϏοτΛަޓ
    ʹ഑ஔͯ͠Τϯίʔυ͠·͢ɻͦͷͨΊɺ୯७ʹ຤ඌΛ࡟Δ͚ͩͰਫ਼౓͕མͪΔੑ࣭͕͋Γ·͢ɻ·
    ͨɺGeoHash ͸఺Ͱ͸ͳ͘ྖҬΛදݱ͠·͢ɻ
    1 จࣈͷ GeoHash Ͱ͸஍ٿن໛Ͱͷେࡶ೺ͳൣғ͔͠දݱͰ͖·ͤΜɻ2 จࣈͷ GeoHash Ͱ͸
    ࠃϨϕϧɺ3 จࣈͷ GeoHash Ͱ͍͍ͩͨ౎ಓ෎ݝϨϕϧͷൣғΛදݱͰ͖·͢ɻ௚ײతͳཧղΛ͢
    Δʹ͸ GeoHash Explorer*3͕͓͢͢ΊͰ͢ɻ
    *2 PlusCode ͸ Open Location Code ʹΑΓੜ੒͞ΕΔ
    *3 https://geohash.softeng.co/
    62

    View full-size slide

  64. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.1 ͸͡Ίʹ
    ਤ 6.1: 1 จࣈͷ GeoHash
    63

    View full-size slide

  65. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.1 ͸͡Ίʹ
    ਤ 6.2: 2 จࣈͷ GeoHash
    64

    View full-size slide

  66. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.1 ͸͡Ίʹ
    ਤ 6.3: 3 จࣈͷ GeoHash
    GeoHash ͷΤϯίʔυ
    ͍͍ͨͯ͸طଘͷϥΠϒϥϦΛ࢖͏ͱࢥ͍·͕͢ɺҢ౓ܦ౓͔Β GeoHash ΁ͷม׵͸࣍ͷΑ͏ʹ
    ߦ͍·͢ɻौ୩εΫϥϯϒϧεΫΤΞͷ͋Δʮ๺Ң 35.65840 ౓ɺ౦ܦ 139.70219 ౓ʯͷม׵Λ௨͠
    ͯઆ໌͠·͢ɻ·ͣɺҢ౓͸ʮೆҢ 90 ౓ˠ๺Ң 90 ౓ʯ
    ɺܦ౓͸ʮ੢ܦ 180 ౓ˠ౦ܦ 180 ౓ʯΛʮ0
    ˠ 1ʯʹม׵͠·͢ɻҢ౓ΛПɺܦ౓ΛЕͱ͢Δͱ࣍ͷΑ͏ͳࣜʹͳΓ·͢ɻ
    ϕ′ = (ϕ + 90)/180
    λ′ = (λ + 180)/360
    ͜ΕΛ࣮ࡍʹ౰ͯ͸ΊΔͱ࣍ͷΑ͏ʹͳΓ·͢ɻ
    (35.65840 + 90)/180 = 0.69810222222...
    (139.70219 + 180)/360 = 0.88806163888...
    65

    View full-size slide

  67. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.1 ͸͡Ίʹ
    ࣍ʹɺ͜ΕΒΛ 2 ਐ਺ʹม׵͠·͢ɻখ਺ͷ 2 ਐ਺දه͕؆୯ʹಘΒΕͳ͍؀ڥͰ͸ɺඞཁͳܻ
    ਺͚ͩϏοτγϑτΛͨ͠ΓɺϧʔϓΛճ͢ͱྑ͍Ͱ͠ΐ͏ɻJavaScript Ͱ͸ 0.768.toString(2)
    ͳͲͱॻ͘ͱ؆୯ʹ 2 ਐ਺දه͕ಘΒΕ·͢ɻ
    લड़ͷ࠲ඪ͸ 2 ਐ਺Ͱදه͢Δͱ࣍ͷΑ͏ʹͳΓ·͢ɻ
    Ң౓: 0.69810222222... ˠ 0.1011001010110110110100111100010110110101100110010011...
    ܦ౓: 0.88806163888... ˠ 0.1110001101011000000000011110111111011100001001001111...
    ͜ΕΒͷখ਺఺ҎԼΛަޓʹฒ΂͍͖ͯ·͢ɻ2 ਐ਺ͷখ਺఺ҎԼΛ্Ґͷܻ͔Βॱʹɺܦ౓͸ح
    ਺ྻɺҢ౓͸ۮ਺ྻͱ͍ͬͨ۩߹ʹɺަޓʹฒ΂͍͖ͯ·͢ɻ
    Ң౓ ˠ .1.0.1.1.0.0.1.0.1.0.1.1.0.1.1.0.1.1.0.1.0.0.1.1.1
    ܦ౓ ˠ 1.1.1.0.0.0.1.1.0.1.0.1.1.0.0.0.0.0.0.0.0.0.0.1.1.
    --------------------------------------------------
    ߹੒ ˠ 11101101000011100110011110010100010100010000011111
    ࠷ޙʹ͜ͷόΠφϦྻΛ BASE32 ม׵͠·͢ɻઌ಄͔Β 5 Ϗοτͣͭ۠੾Γɺද 6.2 ʹΑͬͯม
    ׵͠·͢ɻ
    ද 6.2: BASE32 ม׵ද
    2 ਐ਺ BASE32 2 ਐ਺ BASE32 2 ਐ਺ BASE32 2 ਐ਺ BASE32
    00000 0 01000 8 10000 h 11000 s
    00001 1 01001 9 10001 j 11001 t
    00010 2 01010 b 10010 k 11010 u
    00011 3 01011 c 10011 m 11011 v
    00100 4 01100 d 10100 n 11100 w
    00101 5 01101 e 10101 p 11101 x
    00110 6 01110 f 10110 q 11110 y
    00111 7 01111 g 10111 r 11111 z
    ͖͞΄ͲಘΒΕͨόΠφϦྻ 11101101000011100110011110010100010100010000011111 ΋ 5
    Ϗοτͣͭ۠੾Γɺද 6.3 ͷΑ͏ʹม׵Ͱ͖·͢ɻ
    66

    View full-size slide

  68. ୈ6ষ BigQueryͰGeoHashʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.2 ڥքσʔλͷऔΓࠐΈ
    ද 6.3: BASE32 ม׵݁Ռ
    2 ਐ਺ BASE32
    11101 x
    10100 n
    00111 7
    00110 6
    01111 g
    00101 5
    00010 2
    10001 j
    00000 0
    11111 z
    ʮxn76g52j0zʯ͕ม׵݁ՌͰ͢ɻ͜ͷ GeoHash ͸ɺ๺Ң໿ 35.65839707 ౓ʙ35.65840244 ౓ɺ౦
    ܦ໿ 139.70218062 ౓ʙ139.70219135 ౓ͷྖҬΛ͍ࣔͯ͠·͢ɻ
    6.2 ڥքσʔλͷऔΓࠐΈ
    ࠃ౔ަ௨লͷڥքσʔλΛऔಘɾ੔ܗͯ͠ BigQuery ʹऔΓࠐΈɺGeoHash දݱʹม׵͢Δʹ͋
    ͨΓɺ࣍ͷखॱͰߦ͍·͢ɻ
    1.ʢԼ४උʣࠃ౔ަ௨ল͔ΒڥքσʔλΛऔಘ͠ɺBigQuery ʹऔΓࠐΉɻ
    2.ʢຊ୊ʣBigQuery ্Ͱࢢ۠ொଜͱڥքσʔλͷରԠΛ΋ͱʹɺGeoHash ͱࢢ۠ொଜͷରԠΛ
    ࡞੒͢Δɻ
    ຊઅͰ͸ɺڥքσʔλΛ BigQuery ʹऔΓࠐΉͱ͜Ζ·Ͱղઆ͠·͢ɻGIS Ͱ༻͍ΒΕΔϕΫλ
    σʔλ͸ɺϙΠϯτʢ఺ʣ
    ɺϥΠϯʢઢʣ
    ɺϙϦΰϯʢଟ֯ܗʣͷ 3 छྨ͕͋Γ·͢ɻࠓճ͸ڥքσʔ
    λͰ͢ͷͰɺϙϦΰϯΛऔΓѻ͍·͢ɻ
    ࢢ۠ொଜͷڥքσʔλͱͯ͠ɺࠃ౔ަ௨ল͕ެ։͍ͯ͠Δࠃ౔਺஋৘ใͷߦ੓۠ҬσʔλΛ༻͍·
    ͢*4ɻ͜ͷαΠτͰ͸΄͔ʹ΋தֶߍ۠ͳͲ͞·͟·ͳσʔλ͕ެ։͞Ε͍ͯ·͢ɻར༻ن໿͸ͦΕ
    ͧΕʹ͓͍ͯ֬ೝΛ͓ئ͍͠·͢ɻ
    μ΢ϯϩʔυͨ͠σʔλ͸ jq ίϚϯυ*5Ͱ GeoJSON ͔Β TSV ʹม׵͠ɺbq ίϚϯυ*6Ͱ
    BigQuery ʹऔΓࠐΈ·͢ɻ
    *4 ࠃ౔਺஋৘ใͷߦ੓۠Ҭσʔλ:ɹ https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03-v3_0.html
    *5 jq ίϚϯυ: JSON Λ੔ܗ͢ΔͨΊͷπʔϧ https://stedolan.github.io/jq/
    *6 bq ίϚϯυ: BigQuery Λૢ࡞͢ΔͨΊͷπʔϧ https://cloud.google.com/bigquery/docs/bq-command-line-
    tool?hl=ja
    67

    View full-size slide

  69. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.2 ڥքσʔλͷऔΓࠐΈ
    # σʔλΛμ΢ϯϩʔυʢ೔ຊશࠃͷ2021೥࣌఺ͷσʔλʣ
    $ wget https://nlftp.mlit.go.jp/ksj/gml/data/N03/N03-2021/N03-20210101_GML.zip
    # ZIPΛղౚ͢Δ
    $ unzip N03-20210101_GML.zip
    # GeoJSONΛTSVʹม׵͢Δʢ؀ڥʹΑΓ·͕͢1෼ఔ౓͔͔Γ·͢ʣ
    $ jq -r ’.features
    | to_entries
    | map([
    .key,
    .value.properties.N03_001,
    .value.properties.N03_002,
    .value.properties.N03_003,
    .value.properties.N03_004,
    .value.properties.N03_007,
    .value.geometry
    | tostring
    ])[] | @tsv’ N03-20210101_GML/N03-21_210101.geojson > japan.geo.tsv
    # BigQueryʹҰ୴औΓࠐΉ
    $ bq load --source_format=CSV \
    --field_delimiter=tab geo_dataset.japan_pre \
    ./japan.geo.tsv \
    polygon_id:INT64,city_name_1:STRING,city_name_2:STRING,city_name_3:STRING,\
    city_name_4:STRING,city_id:STRING,city_polygon:GEOGRAPHY
    TSV Λ͍ͬͨΜͦͷ·· BigQuery ʹऔΓࠐΜͩޙɺBigQuery ্Ͱ੔ܗͯ͠औΓࠐΈ௚͠·͢ɻ
    CREATE OR REPLACE TABLE geo_dataset.japan CLUSTER BY polygon_id AS
    WITH pref_number AS (
    SELECT DISTINCT city_name_1, LEFT(city_id, 2) || "000" pref_city_id
    FROM geo_dataset.japan_pre
    WHERE city_name_1 != "null" AND city_id != "null"
    )
    SELECT
    polygon_id,
    -- null͕จࣈྻͰऔΓࠐ·Ε͍ͯΔͨΊNULLʹ௚͓ͯ͘͠
    NULLIF(city_name_1,"null") city_name_1,
    NULLIF(city_name_2,"null") city_name_2,
    NULLIF(city_name_3,"null") city_name_3,
    NULLIF(city_name_4,"null") city_name_4,
    CASE
    WHEN city_id != "null" THEN city_id
    WHEN city_name_1 != "null" THEN pref_city_id -- ॴଐະఆ஍
    ELSE NULL
    END city_id,
    city_polygon
    FROM geo_dataset.japan_pre
    68

    View full-size slide

  70. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    LEFT JOIN pref_number USING (city_name_1)
    ࠷ऴతʹ࣍ͷΑ͏ͳςʔϒϧ͕ BigQuery ʹ࡞ΒΕ·͢ɻ
    ද 6.4: ֤ࢢ۠ொଜͷڥքσʔλ
    ྻ໊ ܕ ಺༰
    polygon_id INT64 ֤ϙϦΰϯʹ෇༩͢Δ ID
    city_name_1 STRING ౎ಓ෎ݝ
    city_name_2 STRING ࢧிɾৼڵہ໊ʢ๺ւಓͷΈɾͦͷ΄͔ͷ৔߹͸ NULLʣ
    city_name_3 STRING ܊ɾ੓ྩ౎ࢢ໊
    city_name_4 STRING ࢢ۠ொଜ໊
    city_id STRING ߦ੓۠Ҭίʔυɹ૯຿ল͕ઃఆ͍ͯ͠Δࢢ۠ொଜͷ੔਺ 5 ܻͷ ID
    city_polygon GEOGRAPHY ڥքΛද͢ϙϦΰϯ
    6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    ຊߘͰ͸ GeoHash ΛΩʔͱͯ͠ɺͦͷൣғʹରԠ͢Δࢢ۠ொଜΛฦ͢ςʔϒϧΛ࡞੒͠·͢ɻ
    GeoHash Ͱද͞ΕΔ௕ํܗ͕Ͳͷࢢ۠ொଜʹඃ͍ͬͯΔ͔Λߟ͑·͢ɻ
    ʮxn5jeʯʹରͯ͠͸ɺ
    ʮ౦ژ
    ౎େౡொʯ͕ฦͬͯ͘Ε͹Α͍Θ͚Ͱ͢ɻ͜ͷςʔϒϧΛ࡞Δʹ͸ɺ͢΂ͯͷ 5 ܻͷ GeoHash λΠ
    ϧɺ
    ʮ00000ʯ͔Βʮzzzzzʯͷ໿ 3355 ສݸʹରͯ͠ɺࢢ۠ொଜͷϙϦΰϯ໿ 12 ສݸʹڞ௨෦෼͕͋
    Δ͔൑ఆΛߦ͑͹Α͍Θ͚Ͱ͕͢ɺ౰વ΋ͬͱޮ཰ͷྑ͍ํ๏͕͋Γ·͢ɻ
    69

    View full-size slide

  71. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    ਤ 6.4: ҏ౾େౡ෇ۙͷ 5 ܻͷ GeoHash
    ೔ຊͷࠃ౔͸ GeoHashʮwv,wy,wu,ws,x5,xh,xj,xk,xn,xp,xr,z0,z2ʯͰ෴͍ਚͤ͘Δ͜ͱ͕஍ਤ͔
    ΒΘ͔Γ·͢ɻͦΕͧΕͷࢢ۠ொଜͷϙϦΰϯ͕ɺ͜ͷ 2 จࣈͷ GeoHash ͷͲΕʢҰͭ΋͘͠͸ෳ
    ਺ʣʹؚ·ΕΔ͔Λ൑ఆ͠·͢ɻ͞ΒʹͦͷதͰಉ༷ͷ͜ͱΛɺ࠶ؼతʹ 3 จࣈɺ4 จࣈͱଓ͚͍ͯ
    ͚͹ɺޮ཰Α͘൑ఆ͕Ͱ͖·͢ɻ
    ຊߘͰ͸ɺ೔ຊશࠃͱ͍͏޿͍ൣғͱਫ਼౓ͷόϥϯεΛߟྀͯ͠ 7 จࣈͷ GeoHash Λ༻͍Δ͜ͱ
    ͱ͠·͢ɻ7 จࣈͷ৔߹ɺ࠷ऴతʹ࡞੒͞ΕΔςʔϒϧͷαΠζ͸ 1.25GBɺϨίʔυ਺͸໿ 2069 ສ
    ͱɺൺֱతऔΓѻ͍΍͍͢αΠζʹͳΓ·͢ɻ
    GeoHash ʹࢢ۠ொଜؚ͕·Ε͍ͯΔ͔൑ఆ͢Δ
    ·ͣɺGeoHash ͷจࣈྻ͔ΒɺGeoHash ͷྖҬΛද͢ϙϦΰϯΛ࡞Δؔ਺Λ࡞Γ·͢ɻ
    70

    View full-size slide

  72. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    query_1_3.sql
    -- geohash_bboxؔ਺ͷࢠؔ਺
    -- lจࣈͷGeoHash͸ɺܦ౓෯͸360 * 2^(-CEIL(l*2.5)), Ң౓෯͸180 * 2^(-FLOOR(l*2.5))ͱͳΔͷ
    Ͱɺ
    -- த৺఺͔Βͦͷ൒෼ΛՃݮ͢Ε͹bounding box͕Ͱ͖Δɻ
    CREATE TEMP FUNCTION geohash_bbox_inner(p GEOGRAPHY, l INT64) AS (
    STRUCT(
    ST_X(p) - 180 * POW(2,-CEIL(l*2.5)),
    ST_Y(p) - 90 * POW(2,-FLOOR(l*2.5)),
    ST_X(p) + 180 * POW(2,-CEIL(l*2.5)),
    ST_Y(p) + 90 * POW(2,-FLOOR(l*2.5))
    )
    );
    -- GeoHashͷbounding boxΛऔಘɻST_GEOGPOINTFROMGEOHASHؔ਺ͰGeoHashͷத৺఺͕औಘͰ͖Δɻ
    CREATE TEMP FUNCTION geohash2bbox(geohash STRING) AS (
    geohash_bbox_inner(ST_GEOGPOINTFROMGEOHASH(geohash), LENGTH(geohash))
    );
    -- bboxΛϙϦΰϯԽ͢Δ
    CREATE TEMP FUNCTION bbox2polygon(
    bbox STRUCT
    ) AS (
    ST_MAKEPOLYGON(ST_MAKELINE([
    ST_GEOGPOINT(bbox.xmin, bbox.ymin),
    ST_GEOGPOINT(bbox.xmin, bbox.ymax),
    ST_GEOGPOINT(bbox.xmax, bbox.ymax),
    ST_GEOGPOINT(bbox.xmax, bbox.ymin)
    ]))
    );
    ࣥච࣌఺ʢ2022 ೥ 8 ݄ʣͰ GeoHash ͱϙϦΰϯ͕ަࠩ͢Δʢڞ௨෦෼Λ΋ͭʣ͔൑ఆ͢Δؔ਺͸
    BigQuery ʹ͸͋Γ·ͤΜɻ͔͠͠ɺϙϦΰϯͱ఺ͷަࠩΛ൑ఆͰ͖Δ ST_INTERSECTS ؔ਺͸͋Δ
    ͨΊɺͪ͜ΒΛ༻͍ͯ൑ఆ͠·͢ɻ্Ͱ࡞ͬͨ GeoHash ͷϙϦΰϯΛ࡞Δؔ਺Λ࢖͍͖ͬͯ·͢ɻ
    2 จࣈͷ GeoHash ʹؚ·ΕΔࢢ۠ொଜͱࢢ۠ொଜຖͷϙϦΰϯ਺Λ֬ೝͯ͠Έ·͠ΐ͏ɻ
    -- (Ϣʔβʔఆٛؔ਺ʹଓ͚ͯ)
    WITH geohash_polygons AS (
    SELECT
    geohash,
    bbox2polygon(geohash2bbox(geohash)) polygon
    FROM UNNEST([
    "wv","wy","wu","ws","x5","xh","xj","xk","xn","xp","xr","z0","z2"
    ]) AS geohash
    )
    SELECT
    geohash_polygons.geohash,
    city_name_1 || city_name_4 city_name,
    COUNT(1) polygon_count
    71

    View full-size slide

  73. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    FROM geo_dataset.japan as j
    JOIN geohash_polygons ON ST_INTERSECTS(geohash_polygons.polygon, j.city_polygon)
    GROUP BY 1,2
    ORDER BY 1,2
    LIMIT 5
    ද 6.5 ͷΑ͏ʹฦ͖ͬͯ·ͨ͠ɻ͏·͘ಈ࡞͍ͯͦ͠͏Ͱ͢ɻͨͩ͜ͷ··Ͱ͸ɺ
    ʮwsʯʹରͯ͠
    ʮ༩ಹࠃொʯ
    ʮੴ֞ࢢʯ
    ʮ஛෋ொʯͷͲΕΛฦͤ͹Α͍ͷ͔෼͔Γ·ͤΜɻ࣮ࡍͷͱ͜Ζʮwsʯʹର͠
    ͯ͸ͲΕ΋ਖ਼ղͰ͢ɻҢ౓ܦ౓Ͱදݱ͞ΕΔ࠲ඪʹରͯ͠ࢢ۠ொଜΛฦ͍ͨ͠ͱ͍͏ݩͷ໰୊ʹཱͪ
    ฦΔͱɺGeoHash ͷܻ਺Λ૿΍͍ͯ͘͠ͱྑͦ͞͏Ͱ͢ɻͦΕͰ΋͍͋·͍ͳ෦෼͸࢒Γ·͢ͷͰɺ
    ࠷ޙʹॲཧ͠·͢ɻ
    ද 6.5: ಈ࡞֬ೝͷԠ౴
    geohash city_name polygon_count
    ws ԭೄݝ༩ಹࠃொ 428
    ws ԭೄݝੴ֞ࢢ 256
    ws ԭೄݝ஛෋ொ 35
    wu ԭೄݝ͏Δ·ࢢ 920
    wu ԭೄݝ༩ಹݪொ 1
    GeoHash ͷจࣈ਺Λ૿΍͍ͯ͘͠
    2 จࣈͷ GeoHash ʹରͯ͠͸ɺ
    ࣍ͷΑ͏ʹ GeoHash ͱͦΕʹଐ͢ΔϙϦΰϯ ID ΛऔಘͰ͖·͢ɻ
    -- (Ϣʔβʔఆٛؔ਺ʹଓ͚ͯ)
    WITH g AS (
    SELECT geohash, bbox_polygon(geohash_bbox(geohash)) polygon
    FROM UNNEST([
    "wv","wy","wu","ws","x5","xh","xj","xk","xn","xp","xr","z0","z2"
    ]) AS geohash
    ),
    c2 AS (
    SELECT g.geohash, polygon_id
    FROM geo_dataset.japan as j
    LEFT JOIN g ON ST_INTERSECTS(g.polygon, j.city_polygon)
    )
    SELECT * FROM c2 ORDER BY 1,2 LIMIT 10
    3 จࣈʹରԠ͢Δʹ͸͜ͷΑ͏ʹ͠·͢ɻ2 จࣈͷ GeoHash ʹશ௨ΓͷจࣈΛ຤ඌʹ௥Ճ͠ɺ3 จ
    72

    View full-size slide

  74. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    ࣈͷ GeoHash Λ࡞Γ·͢ɻͦͷޙɺ3 จࣈͷ GeoHash ͱަࠩ͢ΔϙϦΰϯʹߜΓࠐΈ·͢ɻ
    -- (Ϣʔβʔఆٛؔ਺ʹଓ͚ͯ)
    WITH g AS (
    SELECT geohash, bbox_polygon(geohash_bbox(geohash)) polygon
    FROM UNNEST([
    "wv","wy","wu","ws","x5","xh","xj","xk","xn","xp","xr","z0","z2"
    ]) AS geohash
    ),
    c2 AS (
    SELECT g.geohash, polygon_id
    FROM geo_dataset.japan as j
    LEFT JOIN g ON ST_INTERSECTS(g.polygon, j.city_polygon)
    ),
    c3 as (
    SELECT cp.geohash || last_letter AS geohash, j.polygon_id
    FROM c2 AS cp, UNNEST(SPLIT("0123456789bcdefghjkmnpqrstuvwxyz", "")) AS last_letter
    JOIN geo_dataset.japan AS j USING (polygon_id)
    WHERE
    ST_INTERSECTS(
    bbox_polygon(geohash_bbox(cp.geohash || last_letter )),
    j.city_polygon
    )
    )
    SELECT * FROM c3 ORDER BY 1,2 LIMIT 10
    ಉ༷ʹςʔϒϧ໊ͷ਺ࣈΛม͑ͯίϐʔ&ϖʔετ͍͚ͯ͠͹จࣈ਺ΛͲΜͲΜ૿΍ͤ·͢ɻ7 จ
    ࣈ·Ͱ૿΍͠ɺҰ࣌ςʔϒϧʹอଘ͠·͢ɻ7 จࣈͷ GeoHash ͷൣғ͸໿ 120m ʷ໿ 150m ͱͳΓ
    ·͢ɻ
    73

    View full-size slide

  75. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    ਤ 6.5: 7 ܻͷ GeoHash άϦου
    query_2_3.sql
    -- (Ϣʔβʔఆٛؔ਺ʹଓ͚ͯ)
    CREATE TEMP TABLE c7 CLUSTER BY polygon_id, geohash AS
    WITH g AS (
    SELECT
    geohash,
    bbox_polygon(geohash_bbox(geohash)) polygon
    FROM UNNEST([
    "wv","wy","wu","ws","x5","xh","xj","xk","xn","xp","xr","z0","z2"
    ]) AS geohash
    ),
    c2 AS (
    SELECT
    g.geohash,
    74

    View full-size slide

  76. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    polygon_id
    FROM geo_dataset.japan as j
    LEFT JOIN g ON ST_INTERSECTS(g.polygon, j.city_polygon)
    ),
    c3 as (
    SELECT
    cp.geohash || last_letter AS geohash,
    j.polygon_id
    FROM c2 AS cp, UNNEST(SPLIT("0123456789bcdefghjkmnpqrstuvwxyz", "")) AS last_letter
    JOIN geo_dataset.japan AS j USING (polygon_id)
    WHERE
    ST_INTERSECTS(
    bbox_polygon(geohash_bbox(cp.geohash || last_letter )),
    j.city_polygon
    )
    ),
    c4 as (লུ),
    c5 as (লུ),
    c6 as (
    SELECT
    cp.geohash || last_letter AS geohash,
    j.polygon_id
    FROM c5 AS cp, UNNEST(SPLIT("0123456789bcdefghjkmnpqrstuvwxyz", "")) AS last_letter
    JOIN geo_dataset.japan AS j USING (polygon_id)
    WHERE
    ST_INTERSECTS(
    bbox_polygon(geohash_bbox(cp.geohash || last_letter )),
    j.city_polygon
    )
    ),
    c7 as (
    SELECT
    cp.geohash || last_letter AS geohash,
    j.polygon_id,
    city_id, city_name_1, city_name_2, city_name_3, city_name_4 -- ࠷ޙ͚ͩࢢ۠ொଜ໊ͷ৘ใ
    ΛೖΕ͓ͯ͘
    FROM c6 AS cp, UNNEST(SPLIT("0123456789bcdefghjkmnpqrstuvwxyz", "")) AS last_letter
    JOIN geo_dataset.japan AS j USING (polygon_id)
    WHERE
    ST_INTERSECTS(
    bbox_polygon(geohash_bbox(cp.geohash || last_letter )),
    j.city_polygon
    )
    )
    SELECT * FROM c7;
    ෳ਺ͷࢢ۠ொଜ͕ 1 ͭͷ GeoHash ʹؚ·ΕΔ৔߹
    ෳ਺ͷࢢ۠ொଜ͕ 1 ͭͷ GeoHash ʹؚ·ΕΔ৔߹͸ɺҰ൪ؚ·ΕΔ໘ੵͷ޿͍ࢢ۠ொଜΛ࠾༻͢
    ΔΑ͏ʹ͠·ͨ͠ɻͨͩਖ਼֬ʹܭࢉ͢Δʹ͸ɺަࠩ͢ΔྖҬΛܭࢉ͢Δ ST_INTERSECTION ؔ਺ͱɺ
    75

    View full-size slide

  77. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    ͦͷ໘ੵΛܭࢉ͢Δ ST_AREA ؔ਺Λ૊Έ߹Θͤͯܭࢉ͠·͕͢ɺST_AREA ؔ਺͸ BigQuery Ͱ͸ͳ
    ͔ͥۃ୺ʹ͕͔͔࣌ؒΓ·͢ɻߴ଎ʹҰ൪޿͍ࢢ۠ொଜΛۙࣅ͢Δํ๏ͱͯ͠ɺ΋͏Ұจࣈ૿΍ͨ͠
    8 จࣈͷ GeoHash ΛඞཁͳൣғͰͷΈ༻ҙ͠ɺࢢ۠ொଜؚ͕·Ε͍ͯΔ਺Ͱ໘ੵΛۙࣅ͢Δํ๏͕
    ൺֱతߴ଎ʹಈ࡞͠·ͨ͠ɻ͋Δఔ౓ߦ਺ͷ͋Δ SQL ΫΤϦͰ͕͢ɺ1 ෼൒ఔ౓Ͱ׬ྃ͠·͢ɻ
    query_3_3.sql
    -- (Ұ࣌ςʔϒϧఆٛ c7ʹଓ͚ͯ)
    CREATE OR REPLACE TABLE geo_dataset.japan_geohash7 cluster by geohash as
    WITH
    city_count_by_geohash AS ( -- 7ܻGeoHashʹؚ·ΕΔࢢ۠ொଜΛ਺͑Δ
    SELECT
    geohash,
    COUNT(DISTINCT city_name_1 || city_name_4) city_count
    FROM c7
    GROUP BY 1
    ),
    city_area_by_geohash AS ( -- 7ܻGeoHashʹෳ਺ͷࢢ۠ொଜΛؚΉ৔߹͸ɺ8ܻͰ͸͍ͭ͘ͷλΠϧΛऔ
    ΕΔ͔਺͑Δ
    SELECT
    geohash, city_id, city_name_1, city_name_2, city_name_3, city_name_4,
    COUNT(distinct c) cnt, -- 8ܻͷGeoHashͷ਺
    ARRAY_AGG(distinct polygon_id) polygon_ids -- ࢢ۠ொଜͷϙϦΰϯͷҰཡ
    FROM (
    SELECT
    cp.geohash, c, j.city_id, j.polygon_id,
    cp.city_name_1, cp.city_name_2, cp.city_name_3, cp.city_name_4
    FROM c7 AS cp, UNNEST(SPLIT("0123456789bcdefghjkmnpqrstuvwxyz", "")) AS c
    JOIN (SELECT geohash FROM city_count_by_geohash WHERE city_count >= 2) USING (geohash)
    JOIN geo_dataset.japan AS j USING (polygon_id)
    WHERE ST_INTERSECTS(bbox_polygon(geohash_bbox(cp.geohash||c )), j.city_polygon)
    )
    GROUP BY 1,2,3,4,5,6
    )
    -- ؚ·ΕΔࢢ۠ொଜ͕Ұͭͷ৔߹
    SELECT
    geohash, c7.city_id, city_name_1, city_name_2, city_name_3, city_name_4,
    ARRAY_AGG(distinct polygon_id) polygon_ids,
    ARRAY_AGG(distinct c7.city_id) city_ids
    FROM c7
    JOIN city_count_by_geohash USING (geohash)
    WHERE city_count = 1
    GROUP BY 1,2,3,4,5,6
    UNION ALL
    -- ؚ·ΕΔࢢ۠ொଜ͕2ͭҎ্ͷ৔߹
    SELECT
    geohash,
    city_id,
    city_name_1,
    city_name_2,
    city_name_3,
    city_name_4,
    76

    View full-size slide

  78. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    polygon_ids,
    city_ids
    FROM (
    SELECT geohash, city_id, city_name_1, city_name_2, city_name_3, city_name_4
    FROM city_area_by_geohash
    -- Ұ൪਺ͷଟ͍ࢢ۠ொଜΛબͿɻಉ཰ͷ৔߹͸IDͷए͍ॱ
    QUALIFY ROW_NUMBER() OVER (PARTITION BY geohash ORDER BY cnt DESC, city_id) = 1
    )
    JOIN( -- Ͳͷࢢ۠ொଜΛؚΉ͔
    SELECT
    geohash,
    ARRAY_CONCAT_AGG(polygon_ids) polygon_ids,
    ARRAY_AGG(city_id) city_ids
    FROM city_area_by_geohash
    GROUP BY 1
    ) USING (geohash)
    ͜ͷΑ͏ʹੜ੒ͨ͠ 7 ܻͷ GeoHash ʹΑΔڥքʢࠇઢʣͱ࣮ࡍͷڥքʢ੺ઢʣΛॏͶΔͱਤ 6.6
    ͷΑ͏ʹͳΓ·͢ɻਫ਼౓Λ GeoHash ʹΑΔਪఆ͕ਖ਼͘͠ڥք಺Ͱ͋Δׂ߹ͱఆٛ͢Δͱɺࢢ۠ொଜ
    ͷ໘ੵ͕޿͍஍ҬͰ͸ඞવతʹߴ͘ͳΓɺւԊ͍ͷ஍ҬͰ͸௿͘ͳΓ·͢ɻ౦ژ౎ଟຎ஍ҬͰ͸ 96
    ʙ99 ˋఔ౓ɺ೔ຊશମͷฏۉ͸໿ 98.6 ˋʹͳΓ·ͨ͠ɻ
    77

    View full-size slide

  79. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.3 GeoHash-ࢢ۠ொଜςʔϒϧ
    ਤ 6.6: ौ୩۠෇ۙͷ GeoHash ʹΑΔ۠ڥ
    ˙ίϥϜ: GIS ιϑτΛ༻͍ͨ஍ਤͷ࡞੒
    ຊষͰ͸͍͔ͭ͘ͷ஍ਤΛࢀߟը૾ͱͯ͠ૠೖ͍ͯ͠·͢ɻ͜ΕΒ͸ QGIS ͱ͍͏ϑϦʔͷ
    GIS ιϑτͰ࡞੒͍ͯ͠·͢ɻBigQuery Ͱ஍ཧ৘ใΛදݱ͢Δ GEOGRAPHY ܕΛ CSV ͳ
    ͲͰग़ྗ͢ΔͱɺWell-known text(WKT) ܗࣜͰग़ྗ͞Ε·͢ɻ
    BigQuery Ͱूܭͨ݁͠ՌΛ CSV Ͱग़ྗ͠ QGIS ʹऔΓࠐΉ͜ͱͰɺਤ 6.6 ͳͲ͸࡞੒ͯ͠
    ͍·͢ɻ·ͨ WKT ܗࣜ͸୯७ͳςΩετͰ͢ͷͰɺϧʔϓΛճͯ͠ॎઢͱԣઢΛ WKT Ͱه
    ड़͠ɺਤ 6.3 ͳͲ͸࡞੒͍ͯ͠·͢ɻ
    ·ͨɺഎܠͷ஍ਤλΠϧ͸ OpenStreetMap*7Λ༻͍͍ͯ·͢ɻ
    78

    View full-size slide

  80. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.4 ύϑΥʔϚϯεଌఆ
    6.4 ύϑΥʔϚϯεଌఆ
    Ң౓ɾܦ౓Ͱදݱ͞Εͨ࠲ඪ͕ɺͲͷ౎ಓ෎ݝɾࢢ۠ொଜʹଘࡏ͢Δͷ͔ɺBigQuery ্Ͱ൑ఆ͢
    Δ͜ͱʹཱͪ໭Γ·͢ɻ
    ௨ৗ͸ɺϙϦΰϯʹରͯ͠ ST_CONTAINS ؔ਺Λ༻͍ͨ಺෦൑ఆΛߦ͍ɺ͜͏͍ͬͨ൑ఆΛߦ͍·
    ͢ɻGeoHash Λ༻͍Δͱɺਫ਼౓Λएׯ٘ਜ਼ʹ͢Δ͜ͱͰύϑΥʔϚϯε͕ྑ͘ͳΓ·͢ɻ
    ೔ຊࠃ಺ͷ࠲ඪΛҰ༷ʹϥϯμϜʹੜ੒͠ɺύϑΥʔϚϯεܭଌΛߦ͍·͢ɻ࣍ͷΑ͏ͳूܭΛ
    ߦ͍ɺ࣮ߦ࣌ؒͱεϩοτফඅ࣌ؒΛൺֱ͠·͢ɻද 6.6 ʹࣔͨ݁͠Ռ͸ 3 ճͷࢼߦͷதԝ஋Ͱ͢ɻ
    100 ສߦ·Ͱ͸͋·ΓύϑΥʔϚϯεʹ͕ࠩ͋Γ·ͤΜ͕ɺ1000 ສߦҎ্Ͱ͸໌Β͔ͳ͕ࠩੜ·Ε
    ·ͨ͠ɻ
    BigQuery ͷ࣮ߦ࣌ؒ͸࣮ࡍʹֻ͔ͬͨ࣌ؒͰ͢ɻεϩοτফඅ࣌ؒ͸ʮফඅͨ͠εϩοτ਺ʷ࣌
    ؒʯͰ͢ɻσϑΥϧτͷΦϯσϚϯυྉۚϞσϧͷ৔߹͸ BigQuery ͷΫΤϦͷ࣮ߦྉۚ͸σʔλε
    Ωϟϯྔʹൺྫ͢ΔͨΊɺεϩοτΛେྔʹ࢖ͬͨͱ͜ΖͰྉۚͷ৺഑͸͋Γ·ͤΜ͕ɺϓϩδΣΫ
    τ͋ͨΓͷεϩοτͷׂΓ౰ͯ͸ܾ·͍ͬͯ·͢ɻεϩοτΛେྔʹফඅ͢ΔΫΤϦΛ͍ͭ͘΋ฒྻ
    Ͱ࣮ߦ͢Δͱ஗͘ͳΓ·͢ɻ
    GeoHash Λ༻͍ͨํ๏.sql
    SELECT city_name_1, city_name_2, city_name_3, city_name_4, COUNT(1) c
    FROM geo_dataset.japan_random_places
    JOIN geo_dataset.geohash g ON ST_GEOHASH(ST_GEOGPOINT(lng, lat), 7) = g.geohash
    WHERE id BETWEEN 1 AND 4000000000
    GROUP BY 1,2,3,4 ORDER BY 5 DESC;
    ௨ৗͷํ๏.sql
    SELECT city_name_1, city_name_2, city_name_3, city_name_4, COUNT(1) c
    FROM geo_dataset.japan_random_places
    JOIN geo_dataset.japan j ON ST_CONTAINS(j.city_polygon, ST_GEOGPOINT(lng,lat))
    WHERE id BETWEEN 1 AND 4000000000
    GROUP BY 1,2,3,4 ORDER BY 5 DESC;
    *8 ˜ OpenStreetMap ϥΠηϯε: https://www.openstreetmap.org/copyright/ja
    79

    View full-size slide

  81. ୈ 6 ষ BigQuery Ͱ GeoHash ʹΑΔߴ଎ͳࢢ۠ொଜ൑ఆ 6.5 ͓ΘΓʹ
    ද 6.6: ࢢ۠ொଜ͝ͱͷ݅਺Λ਺͑ͨ৔߹ͷ࣮ߦ࣌ؒʢׅހ͸εϩοτফඅ࣌ؒʣ
    ର৅ͷߦ਺ GeoHash ST_CONTAINS
    10 ສߦ 1s ະຬ (1s) 3s(5s)
    100 ສߦ 3s(10s) 14s(17s)
    1000 ສߦ 1s(38s) 1m5s(36m)
    1 ԯߦ 2s(3m12s) 1m9s(2h10m)
    5 ԯߦ 6s(16m) 1m33s(9h30m)
    10 ԯߦ 14s(43m) 1m50s(20h10m)
    40 ԯߦ 9s(4h21m) 4m29s(3d18h)
    6.5 ͓ΘΓʹ
    BigQuery ্Ͱ GeoHash Λ༻͍ͯ఺͕ڥք಺ʹଘࡏ͢Δ͔Ͳ͏͔ͷ൑ఆΛɺେྔͷσʔλʹର͠
    ͯߴ଎ʹߦ͏ํ๏Λࣔ͠·ͨ͠ɻࢢ۠ொଜҎ֎ͷσʔλʹରͯ͠΋ద༻Ͱ͖·͕͢ɺൣғͱඞཁͳਫ਼
    ౓ʹԠͯ͡ GeoHash ͷܻ਺Λదٓௐઅ͢Δͱྑ͍Ͱ͠ΐ͏ɻ
    80

    View full-size slide

  82. ୈ 7 ষ
    Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ
    2022
    Android Λ౥ࡌ͢ΔσόΠεͷܗଶ͸ϓϥοτϑΥʔϜͷਐԽͱͱ΋ʹଟ༷Խ͍ͯ͠·͢ɻۙ೥
    Ͱ͸ɺෳ਺ͷը໘Λ౥ࡌ͢ΔંΓͨͨΈࣜσόΠε΍ Chromebook ͷΑ͏ͳେը໘σόΠεͳͲʹ
    ࠷దԽ͞Εͨ UX Λఏڙ͢Δ͜ͱ͕ߴ඼࣭ͳΞϓϦͷࢦඪͷҰͭͱͳ͍ͬͯ·͢*1ɻ
    ͜ͷΑ͏ͳσόΠεͷଟ༷Խͱͱ΋ʹɺಈը࠶ੜΞϓϦΛ։ൃ͢ΔࡍͷϕετϓϥΫςΟε͸ࠁʑ
    ͱมԽ͖ͯ͠·ͨ͠ɻ
    ฐ͕ࣾఏڙ͍ͯ͠ΔΧϥΦέಈըίϛϡχςΟʮKARASTAʯ
    *2Ͱ͸ɺϢʔβʔ͕౤ߘͨ͠ಈը΍
    ϥΠϒ഑৴Λշదʹࢹௌ͢ΔͨΊͷ඼࣭޲্ʹ஫ྗ͖ͯ͠·ͨ͠ɻຊষͰ͸ɺ2022 ೥ʹಈը࠶ੜΞ
    ϓϦΛ࡞Δͱͨ͠ΒͲͷΑ͏ʹ࣮૷͢Ε͹Α͍ͷ͔ɺ۩ମతͳϢʔεέʔεͱͱ΋ʹղઆ͠·͢ɻ
    7.1 2022 ೥Ҏલͷྺ࢙ΛৼΓฦΔ
    Android ͷϝδϟʔόʔδϣϯ্͕͕ΔͱɺͦΕʹରԠͨ͠ API Level ͷ Android SDK ͕ϦϦʔ
    ε͞Ε·͢ɻݱ࣌఺Ͱ͸ Android 13 ʹରԠͨ͠ API Level 33 ͷ SDK ͕ར༻ՄೳͰ͢ɻ
    ԼҐޓ׵ੑΛอͪͳ͕Β࠷৽ͷ SDK ͷػೳΛ׆༻͢ΔͨΊʹɺJetpack ͱݺ͹ΕΔϥΠϒϥϦ܈
    ͕ެࣜʹఏڙ͞Ε͍ͯ·͢ɻ2022 ೥ݱࡏͰ͸ Jetpack Λ׆༻ͯ͠ΞϓϦΛ։ൃ͢Δํ๏͕Ұൠతʹ
    ͳ͍ͬͯ·͢ɻ
    ຊઅͰ͸ Android SDK ͱ Jetpack ͷྺ࢙ΛৼΓฦΓɺಈը࠶ੜΞϓϦͷ࣮૷ํ๏͕ͲͷΑ͏ͳม
    ભΛͨͲ͖ͬͯͨͷ͔Λղઆ͠·͢ɻ
    2008 ೥: MediaPlayer
    Android SDK ʹ͸ϦϦʔε౰ॳ͔Βಈը΍Ի੠Λ࠶ੜ͢ΔͨΊͷΫϥε (MediaPlayer) ͕ଘࡏ
    ͠·͢ɻ·ͨɺMediaPlayer Ͱ࠶ੜ͍ͯ͠ΔಈըΛ View ͱͯ͠දࣔ͢ΔͨΊͷ UI ίϯϙʔωϯτ
    *1 https://developer.android.com/quality
    *2 https://karasta.net/
    81

    View full-size slide

  83. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.1 2022 ೥Ҏલͷྺ࢙ΛৼΓฦΔ
    (VideoView) ΋ؚ·Ε͍ͯ·͢ɻ
    ͜ΕΒ͸ API Level 33 ͱͳͬͨݱࡏͰ΋ར༻Ͱ͖·͢ɻ͔͠͠ͳ͕ΒɺݱࡏͰ͸ MediaPlayer ΍
    VideoView Λ࢖ͬͯಈըϓϨΠϠʔΛ࣮૷͢Δέʔε͸গͳ͘ͳΓ·ͨ͠ɻ୅ΘΓʹ ExoPlayer ͱ
    ͍͏ϥΠϒϥϦΛ༻͍࣮ͨ૷ํ๏͕Ұൠతʹͳ͍ͬͯ·͢ɻ͜Εʹ͍ͭͯ͸࣍ͷઅͰৄ͘͠ղઆ͠
    ·͢ɻ
    2014 ೥: MediaSession
    ͜ͷ೥ʹ͸΢ΣΞϥϒϧσόΠε޲͚ͷ Android Wear ΍ंࡌσόΠε޲͚ͷ Android Auto ͕
    ൃද͞Ε·ͨ͠ɻͦΕʹ൐͍ɺεϚʔτϑΥϯͱ֎෦σόΠε͕࿈ܞͯ͠ಈ࡞͢ΔΞϓϦ͕׆ൃʹ։
    ൃ͞ΕΔΑ͏ʹͳΓ·ͨ͠ɻAndroid 5.0 (API Level 21) Ͱ͸ɺ͜ͷ࿈ܞΛ࣮ݱ͢ΔͨΊͷ৽͍͠
    ͘͠Έͱͯ͠ MediaSession ͕ಋೖ͞Ε·ͨ͠*3ɻ
    ΞϓϦ͸ϝσΟΞͷ࠶ੜঢ়ଶ (λΠτϧɺΞʔτϫʔΫɺ࠶ੜҐஔͳͲ) Λ MediaSession Λ௨͡
    ͯ OS ʹެ։͠·͢ɻOS ͸ϝσΟΞͷঢ়ଶΛ֎෦σόΠεͳͲʹදࣔ͠·͢ɻٯʹɺ֎෦͔Βͷϝ
    σΟΞίϯτϩʔϧίϚϯυ (࠶ੜɺఀࢭɺγʔΫͳͲ) ͕ MediaSession Λ௨ͯ͡ΞϓϦʹ௨஌͞
    Ε·͢ɻ
    ਤ 7.1: MediaSession
    MediaSession ͸ Jetpack Media ϥΠϒϥϦͱͯ͠΋ఏڙ͞Ε͓ͯΓɺ͜ΕΛ࢖͏ͱ؆୯ʹ
    MediaSession Λ࣮૷Ͱ͖ΔΑ͏ʹͳ͍ͬͯ·͢ɻৄ͘͠͸࣍ͷઅͰղઆ͠·͢ɻ
    *3 Android 4.0 ͷ࣌఺ͰϩοΫը໘ͳͲ͔ΒϝσΟΞΛίϯτϩʔϧ͢ΔͨΊͷ API (RemoteControlClient) ͕௥Ճ
    ͞Ε͍ͯ·͕ͨ͠ɺMediaSession ͷొ৔ͱͱ΋ʹඇਪ঑ʹͳΓ·ͨ͠ɻ
    82

    View full-size slide

  84. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.1 2022 ೥Ҏલͷྺ࢙ΛৼΓฦΔ
    2017 ೥: Picture-in-Picture
    Android 8.0 (API Level 26) Ͱ͸ Picture-in-Picture (PiP) ͷػೳ͕௥Ճ͞Ε·ͨ͠*4ɻPiP ͸
    ΞϓϦͷը໘Λখ͞ͳ΢Οϯυ΢ͱͯ͠දࣔ͢ΔػೳͰ͢ɻ͜ΕʹΑͬͯɺϢʔβʔ͸ಈըΛࢹௌ͠
    ͳ͕Β΄͔ͷλεΫΛ͜ͳ͢͜ͱ͕Ͱ͖ΔΑ͏ʹͳΓ·ͨ͠ɻ͜ͷ͋ͨΓ͔ΒΞϓϦ։ൃͷைྲྀ͸γ
    ϯάϧ΢Οϯυ΢ͷ࣌୅͔ΒϚϧν΢Οϯυ΢ͷ࣌୅ʹҠΓมΘ͍͖ͬͯ·͢ɻ
    ਤ 7.2: Picture-in-Picture*5
    2020 ೥: Jetpack WindowManager
    Android 10 (API Level 29) Ͱ͸Ϛϧν΢Οϯυ΢ͷαϙʔτ͕͞ΒʹڧԽ͞ΕɺંΓͨͨΈࣜσ
    όΠε΍େը໘σόΠεʹ࠷దԽ͞Εͨ UI Λఏڙ͢ΔͨΊͷ API ͕௥Ճ͞Ε·ͨ͠ɻ·ͨɺ΢Οϯ
    υ΢ͷঢ়ଶݕ஌ͷͨΊͷϥΠϒϥϦͱͯ͠ Jetpack WindowManager ͕৽ͨʹϦϦʔε͞Ε·ͨ͠ɻ
    2022 ೥ݱࡏͰ͸ϚςϦΞϧσβΠϯͷΨΠυϥΠϯͰંΓͨͨΈࣜσόΠε΍େը໘σόΠε޲
    ͚ͷ UI Λߏங͢Δํ๏͕ࣔ͞Ε͍ͯ·͢*6ɻಈը࠶ੜΞϓϦʹ͓͍ͯ͸ɺંΓͨͨΈͷঢ়ଶʹԠ͡
    ͯಈըϓϨΠϠʔͷϨΠΞ΢τΛมߋ͢Δ͜ͱʹΑΔ UX ͷ޲্͕ظ଴Ͱ͖·͢ɻ
    ਤ 7.3: ંΓͨͨΈࣜσόΠε
    *4 Android 7.0 ͷ࣌఺ͰΞϓϦΛ෼ׂදࣔ͢ΔϚϧν΢Οϯυ΢Ϟʔυ͕αϙʔτ͞Ε͍ͯ·͕ͨ͠ɺPiP ͸ Android
    TV ͷΈͰར༻Ͱ͖ΔػೳͰͨ͠ɻ
    *5 Big Buck Bunny, ˜ 2008, Blender Foundation / www.bigbuckbunny.org
    *6 https://m3.material.io/foundations/adaptive-design/overview
    83

    View full-size slide

  85. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.2 ExoPlayer ͱ Jetpack Media3 ʹ͍ͭͯ
    ͜͜·Ͱड़΂ͨΑ͏ʹɺಈը࠶ੜΞϓϦΛ։ൃ͢ΔࡍʹٻΊΒΕΔػೳཁ݅͸ Android ͷਐาͱ
    ͱ΋ʹଟ༷Խ͍ͯ͠·͢ɻ࣍ͷઅͰ͸ɺ͜Ε·Ͱʹ঺հͨ͠ػೳΛ࣮૷͢ΔͨΊʹ༻͍ΔϥΠϒϥϦ
    ʹ͍ͭͯ঺հ͠·͢ɻ
    7.2 ExoPlayer ͱ Jetpack Media3 ʹ͍ͭͯ
    ExoPlayer ͸ Google ͕։ൃ͍ͯ͠ΔϝσΟΞ࠶ੜϥΠϒϥϦͰ͢ɻετϦʔϛϯάܗࣜͷϝσΟ
    Ξͷ࠶ੜ΍޿ࠂͷૠೖͳͲɺMediaPlayer ʹ͸ͳ͍ଟ͘ͷػೳΛඋ͍͑ͯ·͢ɻ
    ҰํɺJetpack ϥΠϒϥϦͷҰͭͰ͋Δ Jetpack Media2 ʹ΋ϝσΟΞ࠶ੜػೳ͕͋Γɺॏෳͨ͠
    ػೳΛ࣋ͭ 2 ͭͷϥΠϒϥϦ͕ڞଘ͍ͯ͠·ͨ͠ɻ͞ΒʹɺJetpack Media2 ͷ MesiaSession ͷػ
    ೳͱ ExoPlayer Λ࿈ܞͤ͞ΔͨΊͷ ExoPlayer Extension ΋ެ։͞Ε͓ͯΓɺMediaSession ͷ࣮
    ૷ํ๏͕ෳࡶԽ͍ͯ͠·ͨ͠ɻ
    ਤ 7.4: Jetpack Media2 ͱ ExoPlayer
    2021 ೥ 10 ݄ɺ͜ΕΒͷ໰୊Λղܾͨ͠৽͍͠ Jetpack ϥΠϒϥϦͰ͋Δ Jetpack Media3*7͕ൃ
    ද͞Ε·ͨ͠ɻMedia3 ʹ͸ ExoPlayer ͕౷߹͞Ε͓ͯΓɺϝσΟΞ࠶ੜʹؔ͢Δ͞·͟·ͳϢʔε
    έʔεΛ୯ҰͷϥΠϒϥϦʹΑͬͯ؆୯ʹ࣮ݱͰ͖ΔΑ͏ʹͳΓ·ͨ͠ɻ
    ౰໘ͷؒ͸ैདྷͷ ExoPlayer ͱ Media3 ͕ฒߦͯ͠ϦϦʔε͞Ε·͕͢ɺैདྷͷ ExoPlayer ͸ক
    དྷతʹඇਪ঑ʹͳΔͨΊɺMedia3 ΁ͷҠߦ͕ਪ঑͞Ε͍ͯ·͢ɻ࠷৽ͷόʔδϣϯͷ ExoPlayer Λ
    ར༻͍ͯ͠Δ৔߹ɺجຊతʹ͸ύοέʔδ໊΍Ұ෦ͷΫϥε໊Λஔ׵͢Δ͚ͩͰ Media3 ΁ͷҠߦ͕
    ׬ྃ͠·͢ɻ͞Βʹɺ͜ͷҠߦ࡞ۀΛࣗಈԽ͢ΔͨΊͷεΫϦϓτ΋ެ։͞Ε͍ͯ·͢*8ɻ
    Ҏ߱ͷ಺༰Ͱ͸ɺ͜ͷ Media3 Λ༻͍ͯಈը࠶ੜΞϓϦΛ࡞੒͢Δํ๏Λ঺հ͠·͢ɻ
    *7 https://developer.android.com/jetpack/androidx/releases/media3
    *8 https://developer.android.com/guide/topics/media/media3/getting-started/migration-guide
    84

    View full-size slide

  86. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    ຊઅͰ͸ɺ·ͣ࢝Ίʹ Jetpack Media3 Λ༻͍ͯγϯϓϧͳಈը࠶ੜΞϓϦΛ࡞੒͠ɺ࣍ʹ
    MediaSession ΍ PiP ͳͲͷߴ౓ͳػೳΛ௥Ճ͢Δํ๏Λ঺հ͠·͢ɻ
    γϯϓϧͳಈը࠶ੜΞϓϦ
    ·ͣ͸࠷΋؆୯ͳಈը࠶ੜΞϓϦΛߟ͑·͢ɻ͜ͷΞϓϦͷΞʔΩςΫνϟͱ࣮૷ྫΛ࣍ʹࣔ͠
    ·͢ɻ
    ਤ 7.5: γϯϓϧͳಈը࠶ੜΞϓϦͷΞʔΩςΫνϟ
    PlayerActivity.kt
    class PlayerActivity : AppCompatActivity() {
    private lateinit var player: ExoPlayer
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // PlayerViewΛදࣔ͢Δ
    val playerView = PlayerView(this)
    setContentView(playerView)
    // PlayerΛ࡞੒ͯ͠PlayerViewʹηοτ͢Δ
    player = ExoPlayer.Builder(this).build()
    playerView.player = player
    // ϩʔΧϧ·ͨ͸ωοτϫʔΫ্ͷಈըͷUriΛࢦఆ͢Δ
    val mediaItem = MediaItem.fromUri(...)
    player.setMediaItem(mediaItem)
    }
    override fun onStart() {
    super.onStart()
    // ϑΥΞάϥ΢ϯυʹͳͬͨΒ࠶ੜΛ࢝ΊΔ
    player.prepare()
    85

    View full-size slide

  87. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    player.play()
    }
    override fun onStop() {
    super.onStop()
    // όοΫάϥ΢ϯυʹͳͬͨΒ࠶ੜΛࢭΊΔ
    player.stop()
    }
    override fun onDestroy() {
    super.onDestroy()
    // PlayerͷϦιʔεΛղ์͢Δ
    player.release()
    }
    }
    ͜ͷྫͰ͸ΞϓϦ͕όοΫάϥ΢ϯυʹͳ͍ͬͯΔؒ͸࠶ੜΛఀࢭ͢ΔΑ͏ʹ͍ͯ͠·͢ɻPlayer
    ͷΠϯελϯε͸ෆཁʹͳͬͨλΠϛϯάͰղ์͢Δඞཁ͕͋ΔͨΊɺΞΫςΟϏςΟͷ onDestro
    y() Ͱղ์͍ͯ͠·͢ɻ
    ϩʔΧϧ·ͨ͸ωοτϫʔΫ্ͷಈըʹΞΫηε͢Δʹ͸దٓύʔϛογϣϯΛઃఆ͢Δඞཁ͕͋
    Γ·͕͢ɺຊষͷείʔϓ͔Β͸গ͠֎ΕΔͨΊઆ໌ΛׂѪ͠·͢ɻ
    MediaSessionService Λ༻͍ͨόοΫάϥ΢ϯυ࠶ੜ
    લड़ͷ࣮૷Ͱ͸ΞΫςΟϏςΟ͕ Player Λอ͍࣋ͯ͠ΔͨΊɺը໘ճసͳͲʹΑͬͯΞΫςΟϏ
    ςΟ͕ഁغ͞ΕΔͱ Player ΋ղ์͞Εͯ͠·͍·͢ɻ͜ΕΛ๷͙ͨΊʹ͸ϑΥΞάϥ΢ϯυαʔϏ
    ε*9Λ࢖༻͠·͢ɻPlayer ͷΠϯελϯεΛΞΫςΟϏςΟͰ͸ͳ͘ϑΥΞάϥ΢ϯυαʔϏεʹ
    อ࣋ͤ͞Δ͜ͱͰɺΞΫςΟϏςΟ͕ഁغ͞Εͯ΋ϝσΟΞͷ࠶ੜΛଓߦͤ͞Δ͜ͱ͕Ͱ͖·͢ɻ
    Media3 ʹ͸͜ΕΛ؆୯ʹ࣮ݱ͢ΔͨΊͷΫϥεͰ͋Δ MediaSessionService ؚ͕·Ε͍ͯ·͢ɻ
    MediaSessionService ͸࣍ͷ͜ͱΛࣗಈతʹߦ͍·͢ɻ
    • ϑΥΞάϥ΢ϯυαʔϏεΛ࣮ߦ͢Δ
    • ௨஌ྖҬʹϝσΟΞΛίϯτϩʔϧ͢Δ UI Λදࣔ͢Δ
    • MediaSession Λ֎෦ʹެ։͢Δ
    ϝσΟΞͷίϯτϩʔϧ͸͢΂ͯ MediaSession Λհͯ͠ߦΘΕΔͨΊɺBluetooth ϔουηο
    τ΍ Wear OS ͳͲΛ࢖ͬͯಈըΛ࠶ੜ/ఀࢭ͢Δ͜ͱ΋ՄೳʹͳΓ·͢ɻ͜ͷΞϓϦͷΞʔΩςΫ
    νϟ͸࣍ͷΑ͏ʹͳΓ·͢ɻ
    *9 https://developer.android.com/guide/components/foreground-services
    86

    View full-size slide

  88. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    ਤ 7.6: MediaSessionService Λ༻͍ͨಈը࠶ੜΞϓϦͷΞʔΩςΫνϟ
    MediaSessionService Λ࢖༻͢Δʹ͸ɺҎԼͷΑ͏ʹ MediaSessionService Λܧঝͨ͠αʔϏεΛ
    ࡞੒͠ɺAndroidManifest ʹ௥Ճ͠·͢ɻ
    PlayerService.kt
    class PlayerService : MediaSessionService() {
    private lateinit var player: ExoPlayer
    private lateinit var mediaSession: MediaSession
    private val mediaSessionCallback = object : MediaSession.Callback {
    override fun onAddMediaItems(
    mediaSession: MediaSession,
    controller: MediaSession.ControllerInfo,
    mediaItems: MutableList
    ) = Futures.immediateFuture(mediaItems.map { mediaItem ->
    // MediaController͔Β౉͞ΕͨUriΛ࠶ੜ͢ΔͨΊʹඞཁͳॲཧ
    mediaItem.buildUpon()
    .setUri(mediaItem.requestMetadata.mediaUri)
    .build()
    })
    }
    override fun onCreate() {
    super.onCreate()
    player = ExoPlayer.Builder(this).build()
    mediaSession = MediaSession.Builder(this, player)
    .setCallback(mediaSessionCallback)
    .build()
    }
    override fun onDestroy() {
    player.release()
    mediaSession.release()
    87

    View full-size slide

  89. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    super.onDestroy()
    }
    override fun onGetSession(controllerInfo: MediaSession.ControllerInfo) = mediaSession
    }
    AndroidManifest.xml
    android:name=".PlayerService"
    android:exported="false"
    android:foregroundServiceType="mediaPlayback">




    αʔϏε্Ͱ MediaSession ͱ ExoPlayer ͷΠϯελϯεΛ࡞੒͠ɺ
    onGetSession() ΛΦʔόʔ
    ϥΠυͯ͠ MediaSession Λฦ͠·͢ɻ͜͜Ͱ࡞੒ͨ͠ ExoPlayer ͸αʔϏεͷ֎෦͔Β௚઀ΞΫ
    ηε͞ΕΔ͜ͱ͸͋Γ·ͤΜɻ֎෦͔ΒͷϝσΟΞίϯτϩʔϧ͸͢΂ͯ MediaSession Λհͯ͠ߦ
    ΘΕ·͢ɻ
    ΞΫςΟϏςΟ͔ΒϝσΟΞΛίϯτϩʔϧ͢ΔྫΛҎԼʹࣔ͠·͢ɻ
    PlayerActivity.kt
    val sessionToken = SessionToken(this, ComponentName(this, PlayerService::class.java))
    val controllerFuture = MediaController.Builder(this, sessionToken).buildAsync()
    controllerFuture.addListener({
    // MediaController͸ExoPlayerͱಉ͘͡PlayerΠϯλϑΣʔεΛ࣮૷͍ͯ͠Δ
    val mediaController = controllerFuture.get()
    playerView.player = mediaController
    // ಈըιʔεΛࢦఆ
    val requestMetadata = MediaItem.RequestMetadata.Builder()
    .setMediaUri(...)
    .build()
    val mediaItem = MediaItem.Builder()
    .setRequestMetadata(requestMetadata)
    .build()
    mediaController.setMediaItem(mediaItem)
    // ࠶ੜ։࢝
    mediaController.prepare()
    mediaController.play()
    88

    View full-size slide

  90. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    }, MoreExecutors.directExecutor())
    SessionToken Λ࢖͏ͱ MediaSession ͔Β MediaController ΛऔಘͰ͖·͢ɻMediaController
    ͸ Player ΠϯλϑΣʔεΛ࣮૷͍ͯ͠·͢ɻ·ͨɺαʔϏε্ʹ͋Δ ExoPlayer ΋ಉ༷ʹ Player
    ΠϯλϑΣʔεΛ࣮૷͍ͯ͠·͢ɻ͢ͳΘͪɺMediaController Λऔಘ͢Δͱ ExoPlayer ͱಉ͡Π
    ϯλϑΣʔεΛ༻͍ͯϝσΟΞΛίϯτϩʔϧͰ͖·͢ɻ
    Picture-in-Picture
    ΞϓϦʹ PiP ͷػೳΛ௥Ճ͢Δεςοϓ͸ҎԼͷ 3 ͭͰ͢ɻ
    1. AndroidManifest ͰΞΫςΟϏςΟͷઃఆΛมߋ͢Δ
    2. ΞΫςΟϏςΟΛ PiP Ϟʔυʹ੾Γସ͑ΔॲཧΛ௥Ճ͢Δ
    3. ΞΫςΟϏςΟ͕ PiP Ϟʔυʹͳͬͨͱ͖ʹ UI Λߋ৽͢Δ
    1. AndroidManifest ͰΞΫςΟϏςΟͷઃఆΛมߋ͢Δ
    AndroidManifest.xml
    android:name=".PlayerActivity"
    android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
    android:supportsPictureInPicture="true" />
    AndroidManifest Ͱ android:supportsPictureInPicture Λ true ʹ͢ΔͱɺΞΫςΟϏςΟ
    ͕ PiP ϞʔυʹରԠ͍ͯ͠Δ͜ͱΛએݴͰ͖·͢ɻPiP ϞʔυʹભҠͨ͠ͱ͖ʹΞΫςΟϏςΟ͕
    ࠶ੜ੒͞ΕΔͷΛ๷͙ͨΊɺandroid:configChanges ͷઃఆ΋௥Ճ͠·͢ɻ
    2. ΞΫςΟϏςΟΛ PiP Ϟʔυʹ੾Γସ͑ΔॲཧΛ௥Ճ͢Δ
    Activity.enterPictureInPictureMode() Λ࣮ߦ͢ΔͱɺΞΫςΟϏςΟ͕ PiP Ϟʔυʹ੾Γ
    ସΘΓ·͢ɻUI ্ͷϘλϯΛλοϓͨ͠ͱ͖ʹ PiP Ϟʔυʹ੾Γସ͍͑ͨ৔߹͸ɺϘλϯͷ onCl
    ickListener Ͱ͜ΕΛ࣮ߦ͠·͢ɻϢʔβʔ͕ϗʔϜը໘ʹ໭Ζ͏ͱͨ͠ͱ͖ʹࣗಈతʹ PiP Ϟʔ
    υʹ੾Γସ͍͑ͨ৔߹͸ɺҎԼͷΑ͏ʹ Activity.onUserLeaveHint() ΛΦʔόʔϥΠυ͠·͢ɻ
    PlayerActivity.kt
    // ϗʔϜը໘ʹ໭Δͱ͖ʹݺ͹ΕΔ
    override fun onUserLeaveHint() {
    if (packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
    89

    View full-size slide

  91. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    try {
    val params = PictureInPictureParams.Builder().build()
    enterPictureInPictureMode(params)
    } catch (e: IllegalStateException) {
    // Ұ෦ͷσόΠεͰ͸FEATURE_PICTURE_IN_PICTURE͕༗ޮͰ΋
    // PiPʹભҠ͢ΔͱΫϥογϡ͢Δ
    }
    }
    }
    PiP ͸ Android 8.0 Ͱ௥Ճ͞ΕͨػೳͰ͕͢ɺҰ෦ͷσόΠεͰ͸ Android 8.0 Ҏ߱Ͱ΋ར༻Ͱ͖
    ͳ͍৔߹͕͋Γ·͢ɻFEATURE_PICTURE_IN_PICTURE ͷϑϥάΛࢀর͢ΔͱɺσόΠε͕ PiP Λα
    ϙʔτ͍ͯ͠Δ͔Ͳ͏͔Λ൑ผͰ͖·͢ɻ͔͠͠ͳ͕ΒɺFEATURE_PICTURE_IN_PICTURE ͕༗ޮͰ
    ͋Δʹ΋͔͔ΘΒͣ PiP Ϟʔυʹ͠Α͏ͱ͢ΔͱΫϥογϡ͢ΔσόΠε΋ଘࡏ͠·͢ɻϨΞέʔ
    εͰ͸͋Γ·͕͢ɺIllegalStateException ΛΩϟον͢Δ͜ͱʹΑͬͯΫϥογϡΛճආͰ͖·͢ɻ
    enterPictureInPictureMode() ͷҾ਺ͱͯ͠౉͢ PictureInPictureParams Ͱ͸ɺPiP Ϟʔυ
    ʹͳͬͨͱ͖ͷ΢Οϯυ΢ͷΞεϖΫτൺ΍දࣔ͢ΔϘλϯͷछྨͳͲΛઃఆͰ͖·͢ɻActivity
    .setPictureInPictureParams() Λ࣮ߦ͢ΔͱɺΞΫςΟϏςΟ͕ PiP Ϟʔυ͔Ͳ͏͔ʹؔ܎ͳ
    ͘ PictureInPictureParams Λߋ৽Ͱ͖·͢ɻಈը࠶ੜΞϓϦͷ৔߹͸ɺಈըͷΞεϖΫτൺʹԠ͡
    ͯ PiP ͷ΢Οϯυ΢ͷΞεϖΫτൺΛมߋ͢Δͱྑ͍Ͱ͠ΐ͏ɻ
    PlayerActivity.kt
    mediaController.addListener(object : Player.Listener {
    override fun onVideoSizeChanged(videoSize: VideoSize) {
    if (packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
    try {
    // ಈըͷΞεϖΫτൺͱPiPͷ΢Οϯυ΢ͷΞεϖΫτൺΛҰகͤ͞Δ
    val params = PictureInPictureParams.Builder()
    .setAspectRatio(Rational(videoSize.width, videoSize.height))
    .build()
    setPictureInPictureParams(params)
    } catch (e: IllegalStateException) {
    e.printStackTrace()
    }
    }
    }
    })
    3. ΞΫςΟϏςΟ͕ PiP Ϟʔυʹͳͬͨͱ͖ʹ UI Λߋ৽͢Δ
    PiP ϞʔυͰ͸ΞΫςΟϏςΟ͕খ͞ͳ΢Οϯυ΢Ͱදࣔ͞ΕΔͨΊɺΞΫςΟϏςΟʹ഑ஔͨ͠
    ϘλϯͳͲ͸λοϓͰ͖ͳ͘ͳΓ·͢ɻΞΫςΟϏςΟ͕ PiP Ϟʔυʹͳͬͨͱ͖ʹಈըҎ֎ͷ UI
    90

    View full-size slide

  92. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    Λඇදࣔʹ͍ͨ͠৔߹ɺҎԼͷΑ͏ʹ addOnPictureInPictureModeChangedListener() Λ࣮ߦ
    ͯ͠ PiP Ϟʔυͷ੾Γସ͑Λ؂ࢹ͠·͢ɻ
    PlayerActivity.kt
    class PlayerActivity : AppCompatActivity() {
    private val pipListener = Consumer { info ->
    if (info.isInPictureInPictureMode) {
    // PlayerViewҎ֎ͷUIΛඇදࣔʹ͢Δ
    } else {
    // PlayerViewҎ֎ͷUIΛදࣔ͢Δ
    }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    addOnPictureInPictureModeChangedListener(pipListener)
    ...
    }
    override fun onDestroy() {
    removeOnPictureInPictureModeChangedListener(pipListener)
    super.onDestroy()
    }
    }
    addOnPictureInPictureModeChangedListener() ͸ Jetpack ͷ ComponentActivity Λܧঝ͠
    ͨΞΫςΟϏςΟͰར༻Ͱ͖·͢ɻJetpack Λར༻͍ͯ͠ͳ͍৔߹͸ΞΫςΟϏςΟͷ onPictureI
    nPictureModeChanged() ΛΦʔόʔϥΠυͯ͠ PiP ϞʔυΛ؂ࢹ͠·͢ɻ
    PlayerActivity.kt
    override fun onPictureInPictureModeChanged(
    isInPictureInPictureMode: Boolean,
    newConfig: Configuration
    ) {
    super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
    if (isInPictureInPictureMode) {
    // PlayerViewҎ֎ͷUIΛඇදࣔʹ͢Δ
    } else {
    // PlayerViewҎ֎ͷUIΛදࣔ͢Δ
    }
    }
    91

    View full-size slide

  93. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    Jetpack Compose Ͱ PlayerView Λදࣔ͢Δ
    ࠷ۙͰ͸ View Ͱ͸ͳ͘ Jetpack Compose Λ༻͍ͯ UI Λߏங͢Δέʔε͕ଟ͘ͳ͍ͬͯ·͢ɻ
    ͔͠͠ͳ͕Β Media3 ͷϓϨΠϠʔ UI ͸ View ͱ࣮ͯ͠૷͞Ε͓ͯΓɺCompose ޲͚ͷ API ͸ࠓ
    ͷͱ͜Ζఏڙ͞Ε͍ͯ·ͤΜɻ
    Compose Ͱߏஙͨ͠ UI ্Ͱ PlayerView Λද͍ࣔͨ͠৔߹ɺҎԼͷΑ͏ʹ Compose ͱ View ͷ
    ૬ޓӡ༻ API Λ࢖༻͠·͢ɻ
    val playerView = remember {
    PlayerView(context)
    }
    DisposableEffect(
    AndroidView(factory = { playerView })
    ) {
    // ը໘Λดͨ͡ͱ͖ʹݺ͹ΕΔ
    onDispose {
    mediaController.release()
    }
    }
    AndroidView Λ࢖༻͢ΔͱɺComposable ͷதͰ View ΛදࣔͰ͖·͢ɻ·ͨɺը໘Λดͨ͡ͱ
    ͖ʹߦ͏Ϧιʔεͷղ์ॲཧ͸ DisposableEffect Λ࢖࣮ͬͯݱͰ͖·͢ɻ
    ંΓͨͨΈࣜσόΠε΁ͷରԠ
    Jetpack WindowManager Λ࢖༻͢ΔͱɺҎԼͷΑ͏ʹͯ͠ંΓͨͨΈࣜσόΠεͷঢ়ଶΛ؂ࢹ
    Ͱ͖·͢ɻ
    PlayerActivity.kt
    lifecycleScope.launch(Dispatchers.Main) {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
    WindowInfoTracker.getOrCreate(this@PlayerActivity)
    .windowLayoutInfo(this@PlayerActivity)
    .mapNotNull { layoutInfo ->
    layoutInfo.displayFeatures
    .filterIsInstance()
    .firstOrNull()
    }
    .collect { foldingFeature ->
    // TODO ંΓͨͨΈͷঢ়ଶʹΑͬͯUIΛߋ৽͢Δ
    foldingFeature.state // ંΓͨͨΜͰ͍Δ͔Ͳ͏͔
    foldingFeature.orientation // ંΓ໨ͷ޲͖
    92

    View full-size slide

  94. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.3 ಈը࠶ੜΞϓϦͷ࡞Γํ
    foldingFeature.occlusionType // ંΓ໨͕ը໘ΛӅ͍ͯ͠Δ͔Ͳ͏͔
    foldingFeature.isSeparating // ը໘ͷྖҬ͕ંΓ໨Ͱ෼ׂ͞Ε͍ͯΔ͔Ͳ͏͔
    }
    }
    }
    WindowInfoTracker.windowLayoutInfo() ͸ WindowLayoutInfo ͷ Flow Λฦ͠·͢ɻWin-
    dowLayoutInfo ʹ͸σόΠεͷંΓͨͨΈঢ়ଶΛද͢ FoldingFeature ͕֨ೲ͞Ε͍ͯ·͢ɻFold-
    ingFeature Λ࢖ͬͯ View ·ͨ͸ Composable ͷϨΠΞ΢τΛߋ৽͢Δ͜ͱͰɺΞϓϦͷ UI ΛંΓ
    ͨͨΈࣜσόΠε޲͚ʹ࠷దԽͰ͖·͢ɻ
    ͜͜Ͱ͸ɺCompose Ͱද͍ࣔͯ͠Δ PlayerView ΛંΓ໨ʹॏͳΒͳ͍Α͏ʹ഑ஔͤ͞Δ࣮૷ྫ
    Λ঺հ͠·͢ɻ
    PlayerScreen.kt
    @Composable
    fun PlayerScreen(
    foldingFeature: FoldingFeature?,
    modifier: Modifier = Modifier
    ) {
    val playerModifier = if (foldingFeature == null ||
    foldingFeature.state == FoldingFeature.State.FLAT
    ) {
    // ંΓͨͨΜͰ͍ͳ͍ͷͰશը໘දࣔ͢Δ
    Modifier.fillMaxSize()
    } else {
    if (foldingFeature.orientation == FoldingFeature.Orientation.HORIZONTAL) {
    // ંΓ໨ͷ্ଆʹϓϨΠϠʔΛ഑ஔ͢Δ
    val playerHeight = with(LocalDensity.current) {
    (foldingFeature.bounds.top - WindowInsets.systemBars.getTop(this)).toDp()
    }
    Modifier
    .fillMaxWidth()
    .height(playerHeight)
    } else { // VERTICAL
    // ંΓ໨ͷࠨଆʹϓϨΠϠʔΛ഑ஔ͢Δ
    val playerWidth = with(LocalDensity.current) {
    foldingFeature.bounds.left.toDp()
    }
    Modifier
    .width(playerWidth)
    .fillMaxHeight()
    }
    }
    Box(
    modifier = modifier
    .fillMaxSize()
    .systemBarsPadding()
    ) {
    93

    View full-size slide

  95. ୈ 7 ষ Android ͷಈը࠶ੜΞϓϦͷ࡞Γํ 2022 7.4 ऴΘΓʹ
    // PlayerViewΛදࣔ͢ΔComposable (લͷ߲Λࢀর)
    VideoPlayer(modifier = playerModifier)
    }
    }
    ંΓ໨ͷ޲͖͕ HORIZONTAL ͷ৔߹ɺը໘͸্Լʹ෼ׂ͞Ε·͢ɻfoldingFeature.bounds Ͱ
    ώϯδͷը໘্ͷҐஔ͕औಘͰ͖ΔͷͰɺ͜ΕΛ࢖ͬͯ PlayerView ͷߴ͞Λܭࢉ͠·͢ɻંΓ໨ͷ
    ޲͖͕ VERTICAL ͷ৔߹͸ը໘͕ࠨӈʹ෼ׂ͞ΕΔͷͰɺಉ༷ʹͯ͠ PlayerView ͷ෯Λܭࢉ͠·
    ͢ɻ͜ͷ Composable Λදࣔ͢Δͱਤ 7.3 ͷΑ͏ʹͳΓ·͢ɻ
    Compose Λ༻͍ͨެࣜͷ࣮૷αϯϓϧͱͯ͠͸ Jetcaster*10͕ࢀߟʹͳΓ·͢ɻ͜ͷαϯϓϧͰ
    ͸্هͷྫͱಉ༷ʹંΓͨͨΈͷঢ়ଶΛ؂ࢹ͠ɺΑΓෳࡶͳϨΠΞ΢τΛߏங͍ͯ͠·͢ɻ
    ·ͨɺView Ͱ UI Λߏங͍ͯ͠Δ৔߹͸ ConstraintLayout Λ༻͍ͯಉ༷ͷ͜ͱ͕࣮ݱͰ͖·͢ɻ
    ConstraintLayout Ͱͷ࣮૷ํ๏ʹ͍ͭͯ͸ެࣜͷσϕϩούʔΨΠυ*11Λࢀর͍ͯͩ͘͠͞ɻ
    7.4 ऴΘΓʹ
    ຊষͰ͸ 2022 ೥ 8 ݄࣌఺Ͱͷ࠷৽ͷ API Λ༻͍ͯಈը࠶ੜΞϓϦΛ։ൃ͢Δख๏ʹ͍ͭͯղઆ
    ͠·ͨ͠ɻࠓޙ΋৽ͨͳϑΥʔϜϑΝΫλΛ࣋ͭσόΠε͕ొ৔͠ɺͦΕʹ൐ͬͯ৽ͨͳ API ͕௥
    Ճ͞ΕΔՄೳੑ͕͋Γ·͢ɻ·ͨɺݱࡏ͸ Android View γεςϜ͔Β Compose ΁ͱҠߦ͢Δա౉
    ظͰ͋ΔͨΊɺಈը࠶ੜͷ UI ίϯϙʔωϯτʹؔͯ͠΋ࠓޙେ͖ͳΞοϓσʔτ͕ߦΘΕΔՄೳੑ
    ͕͋Γ·͢ɻ
    KARASTA Ͱ͸ 2022 ೥ 8 ݄ʹ Media3 Λಋೖ͠ɺMediaSession ʹΑΔϝσΟΞίϯτϩʔϧʹ
    ରԠ͠·ͨ͠ɻ·ͨɺݱࡏ͸৽نʹ௥Ճ͢Δը໘ͷ΄ͱΜͲΛ Jetpack Compose Ͱ࣮૷͍ͯ͠·͢ɻ
    ࠓޙ΋ Android ϓϥοτϑΥʔϜͷมԽʹॊೈʹదԠͰ͖ΔΑ͏ɺΞϓϦͷ඼࣭վળʹ౒Ί͍͖ͯ
    ͍ͨͱࢥ͍·͢ɻ
    *10 https://github.com/android/compose-samples/tree/main/Jetcaster
    *11 https://developer.android.com/training/constraint-layout/foldables
    94

    View full-size slide

  96. ୈ 8 ষ
    Unity Transport ղੳͱܰྔαʔό
    ։ൃ
    8.1 ͸͡Ίʹ
    Unity Transport ͸ɺ௿ਫ४ͳωοτϫʔΫ௨৴ૢ࡞Λఏڙ͍ͯ͠ΔϥΠϒϥϦͰ͢ɻ௨৴ϓϩτ
    ίϧΛಠࣗʹ֦ு͢Δ͜ͱ΋Ͱ͖ɺPipeline ػߏΛ༻͍ͯ RUDP ௨৴΁ΧελϚΠζ͢Δ͜ͱ΋Մ
    ೳͰ͢ɻ·ͨɺNetcode for GameObjects Λ༻͍Δ͜ͱͰϚϧνϓϨΠϠʔήʔϜͷ։ൃޮ཰Λߴ
    ΊΔ͜ͱ͕Ͱ͖·͢ɻ2022 ೥ 6 ݄ʹ͸ϚϧνϓϨΠϠʔήʔϜͷ੍࡞ج൫ͱͳΔ Unity ήʔϛϯ
    άαʔϏε͕ਖ਼ࣜϦϦʔε͞Ε͓ͯΓɺϚϧνϓϨΠϠʔήʔϜͷ։ൃ͕ΑΓ؆୯ʹͳ͖͍ͬͯͯ
    ·͢ɻ
    ͔͠͠ɺ࣮ࡍʹϚϧνϓϨΠϠʔήʔϜͷ։ൃΛߦͬͯΈΔͱɺUnity Editor Λෳ਺্ཱͪ͛ͯ
    ಈ࡞֬ೝΛߦ͏ඞཁ͕͋ΓɺߴεϖοΫͳ։ൃ୺຤Λ༻ҙͰ͖ͳ͍ͱಈ࡞֬ೝࣗମ͕೉͍͠ͱ͍͏໰
    ୊ʹ௚໘͢Δ͜ͱ͕͋Γ·͢ɻຊষͰ͸ɺ͜͏͍ͬͨ՝୊Λղܾ͢ΔͨΊɺUnity Transport ͷ௨৴
    ϓϩτίϧΛֶͼ Unity Editor Λ༻͍ͣʹ௨৴Λߦ͏αʔόΛ։ൃͯ͠Έ·͢ɻ
    8.2 Unity Transport ͷηοτΞοϓ
    Unity Transport ΛऔΓࠐΉखॱ͸ҎԼͷ௨ΓͰ͢ɻ
    1. Unity Editor ͰϓϩδΣΫτΛಡΈࠐΉ
    2. ϝχϡʔ͔ΒʮWindowʯˠʮPackage ManagerʯΛબ୒͢Δ
    3. Package Manager ΢Οϯυ΢ͷࠨ্෇ۙʹ͋Δ
    ʮʴʯ
    ΛΫϦοΫ͠ɺ
    ʮadd by package name...ʯ
    Λબ୒͢Δ
    4.ʮNameʯʹʮcom.unity.transportʯͱೖྗͯ͠ʮADDʯΛΫϦοΫ͢Δ
    ͜ΕʹΑΓ Unity Transport Λར༻Ͱ͖Δ͚ͩͰ͸ͳ͘ɺUnity Transport ͷιʔεΛ֬ೝ͢Δ
    ͜ͱ΋Ͱ͖·͢ɻιʔε͸ Library/PackageCache/[email protected] ҎԼʹ֨ೲ͞Εͯ
    ͓Γɺͪ͜ΒΛࢀরͭͭ͠௨৴ϓϩτίϧΛ֬ೝ͍͖ͯ͠·͢ɻͳ͓ɺ@Ҏ߱͸ Unity Transport ͷ
    95

    View full-size slide

  97. ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 8.3 Unity Transport ͷ௨৴ϓϩτίϧ
    όʔδϣϯΛ͓ࣔͯ͠Γɺࣥච࣌఺Ͱͷόʔδϣϯ͸ 1.2.0 ͱͳ͍ͬͯ·͢ɻ
    ࣮ࡍͷ௨৴಺༰Λ֬ೝ͢Δ৔߹͸ɺWireshark ͳͲͷύέοτΩϟϓνϟΛ༻͍Δͱ؆୯ʹ֬ೝͰ
    ͖·͢ɻຊষͰऔΓ্͛Δ಺༰ͷൣғ಺Ͱ͋Ε͹ɺૹड৴ͨ͠σʔλΛஞҰग़ྗ͢ΔΑ͏ͳ؆୯ͳϓ
    ϩάϥϜΛ༻ҙ͢Δ͚ͩͰ΋े෼Ͱ͢ɻ
    fmt.Println(receivedBytes)
    // ग़ྗྫ: [99 68 48 180 135 41 189 178 213 181]
    for _, b := range receivedBytes {
    fmt.Printf("%X ", b)
    }
    // ग़ྗྫ: 63 44 30 B4 87 29 BD B2 D5 B5
    8.3 Unity Transport ͷ௨৴ϓϩτίϧ
    Unity Transport Ͱ௨৴Λߦ͏αϯϓϧϓϩάϥϜ͸ެࣜαΠτʹαʔό*1ͱΫϥΠΞϯτ*2ͱ΋
    ʹެ։͞Ε͍ͯ·͢ɻ
    αϯϓϧϓϩάϥϜͷಈ࡞Λ؆୯ʹ·ͱΊΔͱɺҎԼͷΑ͏ʹͳΓ·͢ɻ
    1. αʔό͕ UDP ϙʔτΛ։͘
    2. ΫϥΠΞϯτ͕઀ଓཁٻΛૹ৴͢Δ
    3. αʔό͕઀ଓཁٻΛड৴͠ɺडཧͨ͜͠ͱΛ௨஌͢Δ
    4. ઀ଓཱ֬ޙʹɺΫϥΠΞϯτ͕ήʔϜσʔλΛૹ৴͢Δ
    5. αʔό͕ήʔϜσʔλΛड͚औΓɺՃ޻ͯ͠ૹ৴͢Δ
    6. ΫϥΠΞϯτ͕ήʔϜσʔλΛड৴͢Δ
    ·ͨɺαϯϓϧϓϩάϥϜʹ͸ॻ͔Ε͍ͯ·ͤΜ͕ɺUnity Transport ͷ಺෦Ͱ ping ͱ pong Λ
    ૹड৴͍͋ͬͯ͠·͢ɻ
    Ҏ্ͷաఔͰొ৔͢Δ௨৴಺༰͸઀ଓཁٻɺ઀ଓडཧɺήʔϜσʔλɺpingɺpong ͷ 5 छྨͱͳ
    Γ·͢ɻͦΕͧΕ௨৴಺༰͸ڞ௨ͷϔομ෦Λ͓࣋ͬͯΓɺ಺༰ʹԠͨ͡ϘσΟ෦͕ޙʹଓ͖·͢ɻ
    ϔομ෦ͷ௕͞͸ 10 όΠτͰɺ௨৴ͷछผʢ1 όΠτʣ
    ɺϑϥάʢ1 όΠτʣ
    ɺηογϣϯτʔΫϯ
    ʢ8 όΠτʣؚ͕·Ε͍ͯ·͢ɻϘσΟ෦ʹ͍ͭͯ͸ɺ઀ଓडཧʹ͸৽ͨͳηογϣϯτʔΫϯʢ8 ό
    Πτʣؚ͕·ΕɺήʔϜσʔλʹ͸ήʔϜଆͰ٧ΊࠐΜͩόΠτྻؚ͕·Ε͓ͯΓɺαϯϓϧϓϩά
    ϥϜͰ͸ූ߸ͳ͠ 4 όΠτ੔਺ܕͷ਺஋͕ೖ͍ͬͯ·͢ɻͳ͓ɺ઀ଓཁٻɺpingɺpong ͷ 3 छྨ͸
    ϔομͷΈͷ௨৴ͱͳ͓ͬͯΓɺϘσΟ෦͸͋Γ·ͤΜɻ
    ҎԼͰ͸ɺϔομ෦ͷ಺༰ʹ͍ͭͯৄࡉʹݟ͍͖ͯ·͢ɻ
    *1 αʔόαϯϓϧ https://docs-multiplayer.unity3d.com/transport/current/samples/serverbehaviour
    *2 ΫϥΠΞϯταϯϓϧ https://docs-multiplayer.unity3d.com/transport/current/samples/clientbehaviour
    96

    View full-size slide

  98. ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 8.4 ܰྔαʔό։ൃ
    ·ͣɺ௨৴ͷछผʹ͍ͭͯ͸શ෦Ͱ 6 छྨ͋ΓɺҎԼͷΑ͏ͳ஋͕ઃఆ͞Ε·͢ɻ
    • ઀ଓཁٻʢ0ʣ
    • ઀ଓڋ൱ʢ1ʣ
    • ઀ଓडཧʢ2ʣ
    • ੾அʢ3ʣ
    • ήʔϜσʔλʢ4ʣ
    • pingʢ5ʣ
    • pongʢ6ʣ
    ͳ͓ࠓճ͸ɺ઀ଓڋ൱΍੾அʹ͍ͭͯ͸ಛʹऔΓ্͛·ͤΜɻ
    ࣍ʹɺϑϥάʹ͍ͭͯ͸ɺ
    ʮηογϣϯτʔΫϯ͕෇༩͞Ε͍ͯΔ͔ʯ͕ 1 Ϗοτ໨ɺ
    ʮPipeline Λ
    ࢖༻͍ͯ͠Δ͔ʯ͕ 2 Ϗοτ໨ͱͳΔϏοτϑϥάͱͯ͠ߏ੒͞Ε͍ͯ·͢ɻࠓճऔΓ্͛Δ௨৴಺
    ༰ͷதͰ͸ɺ઀ଓडཧ͕௥ՃͷηογϣϯτʔΫϯΛ͍࣋ͬͯΔͨΊϑϥά͸ 1 ͱͳΓ·͢ɻ
    ࠷ޙʹɺηογϣϯτʔΫϯʹ͍ͭͯղઆ͠·͢ɻηογϣϯτʔΫϯ͸ϥϯμϜͳ 8 όΠτͷό
    Πτྻͱͳ͍ͬͯ·͢ɻαʔόͱΫϥΠΞϯτͰηογϣϯτʔΫϯΛڞ༗ͤͣɺ઀ଓཁٻʹೖͬͯ
    ͍ΔηογϣϯτʔΫϯΛαʔό͔Βͷૹ৴ʹ࢖༻͠ɺ઀ଓडཧʹؚ·ΕΔ৽͍͠ηογϣϯτʔΫ
    ϯΛΫϥΠΞϯτ͔Βͷૹ৴ʹ࢖༻͠·͢ɻ
    Ҏ্ͷ௨৴಺༰ͱྲྀΕΛ࣮૷͢Δ͜ͱͰɺUnity ͔Βಠཱͨ͠ܗͰ௨৴Λߦ͏ϓϩάϥϜΛ࡞੒Ͱ
    ͖·͢ɻ
    8.4 ܰྔαʔό։ൃ
    αϯϓϧαʔόΛ࠶ൃ໌͢Δͷʹඞཁͳཁૉ͸ͦΖͬͨͷͰ Go Ͱಉ͡Α͏ͳಈ࡞Λ͢ΔαʔόΛ
    ࡞੒͍͖ͯ͠·͢ɻ
    ·ͣɺ௨৴ͷछผΛҎԼͷΑ͏ʹఆٛ͠·͢ɻ
    const (
    ConnectionRequestType = iota
    ConnectionRejectType
    ConnectionAcceptType
    DisconnectType
    DataType
    PingType
    PongType
    )
    ϑϥάͷऔΓѻ͍ʹ͍ͭͯ͸ɺࠓճ͸઀ଓडཧͰͷΈඞཁͳͨΊ઀ଓडཧΛૹ৴͢Δࡍʹ 1 Λઃఆ
    ͢Δ͜ͱʹ͠·͢ɻ
    ηογϣϯτʔΫϯʹ͍ͭͯ͸ rand.Uint64() Ͱੜ੒͠·͢ɻ
    97

    View full-size slide

  99. ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 8.4 ܰྔαʔό։ൃ
    ௨৴಺༰Λද͢ߏ଄ମ͸ɺϔομ෦ͷΈʢ઀ଓཁٻɺpingɺpongʣ
    ɺ઀ଓडཧɺήʔϜσʔλͷ 3
    ͭΛఆٛ͠·͢ɻ
    type TransportHeader struct {
    Type byte
    Flags byte
    Token uint64
    }
    type ConnectAccept struct {
    TransportHeader
    NewToken uint64
    }
    type UdpData struct {
    TransportHeader
    Num uint32
    }
    αʔόຊମͷ࣮૷Ͱ͸؆୯ͷͨΊΫϥΠΞϯτ͸Ұ͚ͭͩѻ͏΋ͷͱ͠ɺඞཁ࠷௿ݶͷಈ࡞ͷΈఆ
    ٛͯ͠Έ·͢ɻڍಈͱͯ͠͸ɺUDP ϙʔτΛ։͖ɺԿ͔Λड৴ͯ͠͸ฦ౴Λߦ͏ͱ͍͏୯७ͳ΋ͷ
    ͱͳΓ·͢ɻΫϥΠΞϯτͷੜଘ֬ೝ΋ඞਢͰ͸ͳ͍ͨΊলུ͠ɺping Λૹ৴͢Δॲཧ΋ল͖·͢ɻ
    type toyServer struct {
    conn *net.UDPConn
    addr *net.UDPAddr // ઀ଓͨ͠ΫϥΠΞϯτ৘ใ
    recvToken uint64
    }
    func (server *toyServer) run() {
    serverAddr := &net.UDPAddr{
    IP: net.ParseIP("127.0.0.1"),
    Port: 9000,
    }
    conn, err := net.ListenUDP("udp", serverAddr)
    if err != nil {
    panic(err)
    }
    server.conn = conn
    buf := make([]byte, 32)
    for {
    n, addr, err := conn.ReadFromUDP(buf)
    if err != nil {
    panic(err)
    98

    View full-size slide

  100. ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 8.4 ܰྔαʔό։ൃ
    }
    server.addr = addr
    switch buf[0] {
    case ConnectionRequestType:
    server.sendAccept(buf[:n])
    case DataType:
    server.sendData(buf[:n])
    case PingType:
    server.sendPong()
    }
    }
    }
    Ͱ͸ɺฦ౴ͷத਎Ͱ͋Δ઀ଓडཧ sendAcceptɺήʔϜσʔλૹ৴ sendDataɺpong ฦ౴ sendPo
    ng ʹ͍ͭͯݟ͍͖ͯ·͢ɻ
    ઀ଓडཧ sendAccept Ͱ͸ɺ઀ଓཁٻ͔ΒηογϣϯτʔΫϯΛൈ͖ग़͠ɺ৽ͨͳηογϣϯτʔ
    ΫϯΛੜ੒ͯ͠ฦ౴͍ͯ͠·͢ɻෳ਺ͷ઀ଓΛ؅ཧ͢Δ৔߹͸ɺ͜͜Ͱੜ੒ͨ͠৽͍͠ηογϣϯ
    τʔΫϯΛه࿥͓ͯ͘͠ඞཁ͕͋Δ఺ʹ஫ҙ͍ͯͩ͘͠͞ɻ
    func (server *toyServer) sendAccept(bs []byte) {
    var request TransportHeader
    binary.Read(bytes.NewBuffer(bs), binary.LittleEndian, &request)
    server.recvToken = request.Token
    var accept ConnectAccept
    accept.Type = ConnectionAcceptType
    accept.Flags = 1
    accept.Token = server.recvToken
    accept.NewToken = rand.Uint64()
    buf := new(bytes.Buffer)
    binary.Write(buf, binary.LittleEndian, accept)
    _, err := server.conn.WriteTo(buf.Bytes(), server.addr)
    if err != nil {
    panic(err)
    }
    }
    ήʔϜσʔλૹ৴ sendData Ͱ͸ɺ઀ଓडཧͱಉ༷ʹड৴಺༰Λύʔε͠ɺฦ౴಺༰Λੜ੒ͯ͠ૹ
    ৴͠·͢ɻ͜͜Ͱ͸ Unity Transport ͷαϯϓϧͱಉ༷ʹɺड৴ͨ͠ήʔϜσʔλʹ +2 Λߦͬͯฦ
    ౴͍ͯ͠·͢ɻ
    99

    View full-size slide

  101. ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 8.5 ऴΘΓʹ
    func (server *toyServer) sendData(bs []byte) {
    var udpData UdpData
    binary.Read(bytes.NewBuffer(bs), binary.LittleEndian, &udpData)
    var response UdpData
    response.Type = DataType
    response.Flags = 0
    response.Token = server.recvToken
    // αϯϓϧαʔόͷڍಈʹ߹Θͤͯ +2 Λ͢Δ͚ͩ
    response.Num = udpData.Num + 2
    buf := new(bytes.Buffer)
    binary.Write(buf, binary.LittleEndian, response)
    _, err := server.conn.WriteTo(buf.Bytes(), server.addr)
    if err != nil {
    panic(err)
    }
    }
    ࠷ޙʹ pong ฦ౴ sendPong Ͱ͸ɺड৴಺༰͸ಛʹඞཁͳ͍ͨΊ pong Λੜ੒ͯ͠ૹ৴͢ΔͷΈͱ
    ͳ͍ͬͯ·͢ɻ
    func (server *toyServer) sendPong() {
    var pong TransportHeader
    pong.Type = PongType
    pong.Flags = 0
    pong.Token = server.recvToken
    buf := new(bytes.Buffer)
    binary.Write(buf, binary.LittleEndian, pong)
    _, err := server.conn.WriteTo(buf.Bytes(), server.addr)
    if err != nil {
    panic(err)
    }
    }
    Ҏ্͕αʔό࣮૷ͷৄࡉͱͳΓ·͢ɻ͜ͷαʔόΛىಈ͠ɺUnity Editor ʹͯΫϥΠΞϯταϯ
    ϓϧΛ࣮ߦ͢Δͱ઀ଓ͔ΒήʔϜσʔλͷૹड৴·ͰߦΘΕΔ͜ͱ͕֬ೝͰ͖·͢ɻ
    8.5 ऴΘΓʹ
    Unity Transport Λղੳ͠ɺαϯϓϧαʔόͱࣅͨಈ࡞Λ͢ΔϓϩάϥϜΛ࡞੒ͯ͠Έ·ͨ͠ɻα
    ϯϓϧϓϩάϥϜΛΤϛϡϨʔτ͢Δ͚ͩͰ͋Ε͹ɺ਺छྨͷ௨৴಺༰Λԡ͑͞Δ͚ͩͰ࣮૷Ͱ͖·
    ͨ͠ɻ
    100

    View full-size slide

  102. ୈ 8 ষ Unity Transport ղੳͱܰྔαʔό։ൃ 8.5 ऴΘΓʹ
    ࠓճऔΓ্͛ΒΕͳ͔ͬͨ Pipeline ػߏΛ༻͍ͨ RUDP ௨৴΍ΑΓ࣮ફతͳαʔό։ൃʹ͍ͭͯ
    ͸ɺػձΛ͋ΒͨΊͯ·ͱΊΒΕͨΒͱࢥ͍·͢ɻ
    101

    View full-size slide

  103. ஶऀ঺հ
    ٢઒ ༐ଠ࿠ (ୈ 1 ষ୲౰, GitHub: yutaroyoshikawa)
    2021 ৽ଔɻTIPSTAR ࣄۀ෦ͰΤϯδχΞΛ͍ͯ͠·͢ɻWebGL ͱ ΞΫηγϏϦςΟʹͭ
    ͍ͯߟ͑Δͷ͕޷͖Ͱ͢ɻ
    ɹ
    দݪ ৴஧ (ୈ 2 ষ୲౰)
    ॴଐ͸ϞϯεταʔόνʔϜͰ Ruby ΍ Go Λॻ͍ͯΔɻϓϩάϥϛϯά͕޷͖Ͱɺීஈ͸ਪ
    ͠ݴޠͷ Haskell Ͱ༡ΜͩΓɺ৽͍͠ϓϩάϥϛϯάݴޠΛษڧͨ͠Γ͍ͯ͠ΔɻHaskell-jp
    ΍ Elm-jp Ͱͪΐͪ͜ΐ͜׆ಈ΋͍ͯ͠Δɻ
    ɹ
    ߐാ ୓࠸ (ୈ 3 ষ୲౰, Twitter: @MeguruMokke)
    2021 ৽ଔɻTIPSTAR ࣄۀ෦Ͱ൚༻తʹ׆ಈ͍ͯ͠·͢ɻझຯ͸͓ֆඳ͖ͱ Clojure ͱ͔ɻ
    ɹ
    ؙඌ Ұਅ (ୈ 4 ষ୲౰, Twitter: @Taillook)
    2019 ৽ଔɻ഑ଐ࣌ΑΓΦϑϥΠϯΠϕϯτͷγεςϜपΓͷ։ൃʹैࣄɻ2022 ೥ 8 ݄͔Β͸
    ԣஅతͳٕज़ࢧԉʹैࣄɻझຯ͸μΠϏϯάͱϥʔϝϯ԰८Γɻ
    ɹ
    ాಹล ً (ୈ 5 ষ୲౰)
    ։ൃຊ෦ CTO ࣨॴଐɻιϑτ΢ΣΞΤϯδχΞͱͯ͠ήʔϜ։ൃͱӡӦɺͦΕ͔Βऩӹੑ΍
    ήʔϜੑͱ UX ໘౳ʑΫϦΤΠςΟϒʹ΋ܞΘ͖ͬͯ·ͨ͠ɻϓϩάϥϛϯάڭҭʹ͍ͭͯ
    ͷֶशιϑτͱΧϦΩϡϥϜΛࣗࣾ಺Ͱ࡞Γɺதɾߴߍੜʹ޲͚ͯϓϩάϥϛϯάߨ࠲ͷߨࢣ
    Ͱ΋׆ಈதɻ΄͔ࣾ಺ R&D ۀ຿΋ࢀՃɻ
    103

    View full-size slide

  104. ෇࿥ ஶऀ঺հ
    ๺ౡ ঵ޔ (ୈ 6 ষ୲౰)
    2019 ৽ଔɻϞϯετͳͲͷ෼ੳ༻σʔλج൫ߏஙΛओʹ୲౰͍ͯ͠·͢ɻBigQuery ͕޷͖ɻ
    ɹ
    ௥ా ହ޺ (ୈ 7 ষ୲౰)
    KARASTA ͷ Android/iOS ΞϓϦΛ࡞Δ࢓ࣄΛ͍ͯ͠·͢ɻKARASTA Ͱ͸ௌ͖ઐͱͯ͠
    ೔ʑ׆ಈ͍ͯ͠·͢ɻ
    ɹ
    ࡾ্ ൏ਓ (ୈ 8 ষ୲౰, Twitter: @kawakami_o3)
    ϞϯετεϐϯΦϑԣஅਪਐάϧʔϓͰαʔόʔ։ൃͷαϙʔτΛ͍ͯ͠·͢ɻଟछଟ༷ͳ
    ϓϩδΣΫτ΍࠾༻ٕज़ʹ࢛ۤീۤͭͭ͠ɺ೔ʑษڧ͠ͳ͕Β͓ख఻͍͍͍͍ͤͯͨͩͯ͞
    ·͢ɻ
    ɹ
    ܀ྛ խਓ (Graphic designer)
    σβΠϯຊ෦ϓϩμΫτਪਐάϧʔϓॴଐɻΞΠίϯΠϥετɾදࢴσβΠϯΛ୲౰͠·͠
    ͨɻUI σβΠϯ΋खֻ͚·͢ɻͱΜ͔͕ͭ޷͖Ͱ͢ɻ
    ɹ
    تଟ ޭ࣍ (੍࡞ਐߦ, Twitter: @kojikita)
    CTO ࣨ DevRel άϧʔϓͰษڧձ΍Πϕϯτɺ৽ଔٕज़ݚमͳͲͷӡӦΛ͍ͯ͠·͢ɻ࠷ۙ
    ͷ஫ྗࣄۀ͸ࢠҭͯͰ͢ɻ
    ɹ
    ӹࢁ ઍय़ (੍࡞ਐߦ, Twitter: @charlielog_ggg)
    CTO ࣨ DevRel άϧʔϓͰɺΤϯδχΞͷΠϯλϏϡʔهࣄΛॻ͍ͨΓɺΠϕϯτڠࢍؔ࿈
    ͷ΍ΓͱΓΛͨ͠Γ͍ͯ͠·͢ɻࣾ಺ͷʮϚʔϒϧϫʔΫελΠϧ੍౓ʯͷԸܙʹ༬͔ͬͯɺ
    ۙʑ஍ํҠॅ༧ఆͰ͢ʂ
    104

    View full-size slide

  105. MIXI TECH NOTE #08
    2022 ೥ 9 ݄ 10 ೔ɹॳ൛ୈ 1 ࡮ɹൃߦ
    ஶɹऀ גࣜձࣾ MIXI ༗ࢤ
    ൃߦॴ גࣜձࣾ MIXI
    ҹ࡮ॴ άϥϑΟοΫ
    ɹ
    ˜ MIXI

    View full-size slide