今日から使えるim@sparql術

アイドルマスター Advent Calendar 2020 4日目の記事です。

はじめに

冬優子ーー!!!誕生日おめでとーーー!!!

はい。
明日はアイマスハッカソンです。ご準備~?

imas.connpass.com

というわけでですね、おそらく今日から準備をしている人に向けて、「今日から使えるim@sparql術」を紹介しようと思います。

sparql.crssnky.xyz

数式を使う

体表面積、考えたこと無いけど合ってるんすかね?
10,11,12行目のbind句とその中身が注目ポイントです。bind句はas句と一緒に使います。where句の中で関数の戻り値や他の変数を別の変数に代入する際に使います。
値 as ?変数名のように、左から右に流れるのは慣れないかもしれませんね...
中では四則演算やmath関数が使われています。

XQuery and XPath Functions and Operators Math Namespace Document

Using Math Functions with SPARQL — GraphDB Free 9.4.0 documentation

に多くの関数があるので、必要に応じて使っていきましょう。

述語を連結して使う

10行目のschema:member/rdfs:labelが注目ポイントです。ユニットに所属するメンバーのURIschema:memberで取得した後、そのURIを主語にしてrdfs:labelで名称を取得できます。これを使えば、

のように、簡単に平均身長を抜き出すこともできます。

他のエンドポイントと繋がる

なんたって、LinkedOpenDataですから。他のエンドポイントと繋がってこそです。
こちらは、とある魔術シリーズに関するエンドポイント「とあるSPARQL」とim@sparqlが繋がる例です。
7行目のSERVICE句が注目ポイントです。
ここで別のエンドポイントを指定することで、別のエンドポイントに対してクエリを送ることができます。その結果と元のエンドポイントのクエリを統合することで、複数のエンドポイントの結果を纏めることができます。

WikipediaからLODを作成するDBpedia(更新が2016年で止まってる...)や、LODをWiki化して人間とコンピュータの双方が参照可能なDBであるWikidataなど、多種多彩なLODが世の中にあるので、ぜひご活用ください。

クエリを探す

im@sparqlのトップページにあるExampleに、少しだけクエリ例があります。また、JavaScriptの例も載せていますのでぜひご参考に。

☆ピコピコプラネット☆SPACEにも、im@sparqlや他のエンドポイントのクエリがたくさん共有されています。先人の知恵をどんどん吸収していきましょう。

space.pikopikopla.net

おわりに

以上です。im@sparqlを活用して、素早くアイマスエンジニアリングを制作していきましょう!!

あんたはここでふゆと死ぬクエリ解説

Linked Open Data Advent Calendar 2020 4日目の記事です。

「あんたはここでふゆと死ぬのよ」
なぜか流行ってしまった、シャニマスの黛冬優子のセリフ。
いや、彼女のセリフではありません。喋ってないのに流行ってしまった、謎のネットミームです。
今年の「ネット流行語100」にもノミネートされているみたいで、シャニマス界隈でたいへんな盛り上がりをみせていました。

このセリフ?は、「あんたはここで」「ふゆと死ぬのよ」で7文字・7文字で分けることができ、短歌の下の句にピッタリだということもよく注目されていました。そこで、百人一首 on SPARQLを利用して、様々な百人一首の和歌をミームで染めていこうと思います。

各歌が上の句・下の句で別れているため、かなり簡単なクエリで実現することができました。では、解説していきます。

  1. 百人一首 on SPARQLの語彙のためにPrefixを定義します。
  2. (空行)
  3. 詠み人と歌自体を取得します。
  4. (where句)
  5. ogura:Poetで詠み人を取得します。
  6. ogura:UpperPhraseで上の句を取得します。
  7. 歌を組み立てます。まず、concat句で上の句と例の文字列を結合します。
    そして、bind句でconcat句の戻り値を変数に格納します。
  8. 表示順序をランダムにします。また、100首は多いので10首に絞っています。

以上!

SObjectPropertyEntryBoxでActorアセットを選択する話

Unreal Engine 4 (UE4) その2 Advent Calendar 2020 4日目の記事です。

SObjectPropertyEntryBoxでAllowedClassにActorを入れると、Levelに存在するActorの中から選ばされるから、ActorのBlueprintアセットを選択するようにするちょいテクニックの話。

はじめに

Editor Utility Widgetしてますか?
良いっすよねEUW。
Slateはまぁ分かるっちゃ分かるような気がするけど、黒魔術感が半端ない。Slotを呼び出してしつつ、[]入れ子にする。まぁ分かるよ。C++にしては直感的だけどさ....
それに比べてEUWはUMGとBlueprintで書けちゃう。惚れてまうやろ。

とはいえ、パーツ数はそんなに多くない。まぁそうだよね。Slateにあるんだから。
SlateにあるものはUMGでも使えます。でもそのままじゃ使えないので、NativeWidgetHostというもので、UMGへ公開してあげる必要があります。
NativeWidgetHostは、単一のSlateや自分で組んだSlate群をUMGに昇格(上も下もないが...)するクラスです。
詳しい実例は、あまりにも有名な以下のページへ。

unwitherer.blogspot.com

SObjectPropertyEntryBoxを使う

EUWで欲しいパーツの1つでもあるSObjectPropertyEntryBox。
よく見るやつです。BP_Sky_Sphereとかでも光源を選ぶ時に使うやつ。

f:id:crssnky:20201025222200p:plain

実はこれ、許可するクラスを選択する時にActor以外を選ぶと、アセットを選ぶことができます。こちらはTextureクラスを指定した様子。 f:id:crssnky:20201107221334p:plain

SObjectPropertyEntryBoxの元となったPrivateなSlate、SPropertyEditorAssetの308行目にそれっぽい判定はあります。

bIsActor = ObjectClass->IsChildOf(AActor::StaticClass());

Actor継承系を指定するとActor選択用のUIになり、それ以外だとアセット選択用のUIになるわけです。(上のIsChildOf判定の後にそれぞれのSlateを仕込む文がある)

Actorアセットを選択したい

EUWをやっていると、ActorのBlueprintアセットを自動編集させたいことがあると思います。しかし、単純にSObjectPropertyEntryBoxのAllowedClassにActorを入れてしまうと、Level内から選ばされてしまいます。

SAssignNew(m_entryBox, SObjectPropertyEntryBox)
    .AllowedClass(targetClass) // UClass* targetClassとしてBlueprintからActorを入れてあげる
    .OnShouldFilterAsset_Lambda([this](const FAssetData& assetData){return false;});

f:id:crssnky:20201108160529p:plain でも本当に欲しいのは、こっちです。 f:id:crssnky:20201110231454p:plain

え?SClassPropertyEntryBoxを使えって?
サムネイルがあった方が便利じゃないです?
(ツリー状態で見たい場合はSClassPropertyEntryBoxを使いましょう)

SObjectPropertyEntryBoxの設定を頑張る

主に使用する設定は以下の通り

  • AllowedClass
    • 許可するクラスをUClass*で指定する
  • OnShouldFilterAsset_Lambda
    • AllowedClassに加え、見つかった個々のアセットに対してさらにフィルターするか判別する関数

これらを使用して、UNativeWidgetHostするならばこうなります。

  • 05行目:許可したいクラスがBlueprintかどうかを調べる
  • 09行目:許可したいクラスがBlueprintだった場合はUBlueprintを、そうでない場合は入力した許可したいクラスをAllowedClassとする
  • 10行目:フィルター関数を定義する
  • 12行目:許可したいクラスがBlueprintかどうかで場合分け
    • 26行目:Blueprintじゃない場合は何もフィルターしない(falseを返す)。
  • 15行目:Blueprintのアセットのはずだけど、一応nullptrチェック
  • 17行目:検査対象のBlueprintのParentClass(Blueprintが持つクラス)が、許可するクラスを継承しているかどうか
    • trueだとフィルターする(画面に表示しない)ので、IsChildOf()の結果を反転する

こうすることで本当に欲しかった、targetClassにActorを選んでもそのActorを継承したクラスを持つBlueprintアセットを選択することができるウィジェットを実現することができます。

UNativeWidgetHostを継承したクラス全体も公開します。
みなさんも、良いEditorUtilityWidgetライフを!

今すぐ使えるソース全体はこちら↓
crssnky/UBlueprintSelectBox.cpp

im@sparqlのすゝめ

Linked Open Data Advent Calendar 2020 1日目の記事です。

sparql.crssnky.xyz

当ブログでは何度も記事にしているim@sparqlです。

IM@S(アイドルマスター) + SPARQL = im@sparql

つまり、アイドルマスターの世界がSPARQLで検索できるということです。
(VR Readyという単語に倣って、アイマスが"SPARQL Ready"と言ってみてる)

利用者のターゲットは、アイマスエンジニアです。
アイマスエンジニアとは、エンジニアリングを通じてアイマスにContributeする(二次創作的な活動を行う)人を指します。
何かを制作する際、必要な情報をDBやファイル等に書き出しておく必要があるときがありますが、各アイマスエンジニアがそれぞれ必要な情報を1から構築し、利用できるようにするのは削減できる手間だと考えました。
個々の作品に囚われず、誰もが汎用的に使えるDBがあれば...
そんな思いからこのデータベースが生まれました。

まぁ、「自分がアイマスの知識をSPARQLで検索したい。」ってのも半分ありますが....

SPARQLの書き方を覚えるという手間は増えてしまいますが、アイマスに関する情報群を自分で構築し、利用できるようにする必要はなくなります。これにより、アイマスエンジニアリングの障壁が低くなると思っています。

たとえば...

このようなクエリを書くだけで、アイマスのアイドルのイメージカラーを一挙に取得することができます。また、im@sparqlは更新し続けているため、新たなアイドルが登場及び既存アイドルのイメージカラーが追加されても作品を改修する必要はありません。

im@sparqlの情報を上手く利用することで、以下のようなWebアプリ(作:@myskngさん)を作成することができます。

illumituner.firebaseapp.com

im@sparqlには以下のようなドキュメントサイトも用意してますので、ぜひご活用して、プロデュースの手助けになるツールを作ってみてください!!

doc.crssnky.xyz

im@sparqlの構成について

#オタクLOD発展のため、im@sparqlのバックエンドにまとめる。

SPARQLエンジン

Apache Jena Fuseki2を利用。Fuseki2はファイルからグラフを構築する場合、更新するときは再起動が必要なためDockerコンテナで管理しています。Imageはこいつ。

hub.docker.com

設定ファイルはこんな感じです。Readだけ許可し、Updateクエリ等は通さない。ファイルはhttp経由で取っても絶対パスを書いても良し。

@prefix fuseki:  <http://jena.apache.org/fuseki#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
@prefix tdb:     <http://jena.hpl.hp.com/2008/tdb#> .
@prefix ja:      <http://jena.hpl.hp.com/2005/11/Assembler#> .
@prefix :        <#> .

<#service1> rdf:type fuseki:Service ;
    fuseki:name "/imas" ;
    fuseki:serviceQuery "query" ;
    fuseki:serviceReadGraphStore    "data" ;
    fuseki:dataset  <#imas>;
.

<#imas>    rdf:type ja:RDFDataset ;
    rdfs:label "imas" ;
    ja:defaultGraph 
      [ rdfs:label "imas" ;
        a ja:MemoryModel ;
        ja:content [ja:externalContent <https://sparql.crssnky.xyz/imasrdf/RDFs/765AS.rdf> ] ;
        ・・・
        ja:content [ja:externalContent <https://sparql.crssnky.xyz/imasrdf/URIs/imas-schema.ttl> ] ;
      ];
    .

自動更新

詳しくは書かないが、GitHubリポジトリからマージを監視し、そのたびにサーバー上のファイルを更新してDockerコンテナを再起動しています。

Webサーバー

お前いまどきWebサーバーにApache使ってるのかよって感じですが、元々はTomcat上でFuseki2動かしてたからね。しょうがないね。
ここではSSL設定したり、リバースプロキシでFuseki2のプロセスへhttp通信を橋渡ししたりしてます。

IM@S ENGINEERS ON@IR!!!! 2020の会場設営係

手づくりの武道館~♪

f:id:crssnky:20201019001802p:plainf:id:crssnky:20201019001814p:plain

というわけで、IM@S ENGINEERS ON@IR!!!! 2020の会場設営を行いました。
そういえば書いてなかったので、書きます。

IM@S ENGINEERS ON@IR!!!! 2020とは

imas.connpass.com おなじみのIM@Studyのセッション&LTイベントであるEngineers T@lkイベントが世間の状態を考慮して、オンラインイベントとして開催されました。
光る棒がある・アバターが決められるという理由もあってプラットフォームはclusterを採用しました。もちろん、定番のYoutube配信もあります。

youtu.be

手づくりの武道館

clusterではUnity経由で自作のワールドをアップロードできます。
そこで、登壇=ステージに立つ、つまり発表者=アイドルという某氏の理論に則り、IM@Studyライブ劇場を(勝手に)建築することにしました。

たしか、スタッフキックオフのタイミングでは作ることは確定していなかったような気がします(冗談レベルの話はあった)。作ってる進捗をなんとなくTwitterに流し続けて、直前ミーティングで招いてレビューしてもらい、OKを頂いた形でした。

作り方

UE4のBrushツールで形を整え、FBX出力を行い、それをUnityへ引っ張ってくる方法を取りました。
いやいや、モデリングツール(Blender)なんも分からん。
詳しいことはこちらを見てください。

建物等のプリミティブな形の組み合わせのものならBrushツールによるモデリングが一番良いまであります。
BrushツールはVolumeを決めるだけなので、重なった部分には面を作らないからです(詳しいことはスライド見て)。
公式ドキュメントも貼っておこう。

docs.unrealengine.com

みんなも作れそうな気がしますよね?じゃ、期待してるよ!!

RedisGraphの気になったのをもうちょい試す

はじめに

crssnky.hatenablog.jp

前回やり残したことをやります。
というのも、エッジに任意の属性が付けられるというもの。
RDFでは、許可されたものしか付けられないため試してみました。

本編

準備

RedisGraphのQuickStart通り、

docker run -p 6379:6379 -it --rm redislabs/redisgraph

を立ち上げておきます。

グラフ構築

GRAPH.QUERY imasparql "CREATE (:Idol {name:'如月千早'})-[:callTable {called:'風花さん'}]->(:Idol {name:'豊川風花'})"
GRAPH.QUERY imasparql "CREATE (:Idol {name:'如月千早'})-[:callTable {called:'春香'}]->(:Idol {name:'天海春香'})"

f:id:crssnky:20200812154945p:plain

千早さんの呼称表から"豊川風花""天海春香"を登録しています。それぞれのエッジには"どう呼んでいるか"をcalledで登録しています。

検索

GRAPH.QUERY imasparql "MATCH (caller:Idol)-[c:callTable]->(callee:Idol) WHERE caller.name='如月千早' RETURN caller.name,callee.name, c.called"

呼称表の中から千早さんのものを検索し、呼ぶ側・呼ばれる側・どう呼んでいるかを表示します。

caller.name
callee.name
c.called
如月千早
豊川風花
風花さん
如月千早
天海春香
春香

エッジの属性が取れました。

おわりに

ノードだろうがエッジだろうが好き勝手に属性を付けて良いみたいですね。
im@sparqlは全てをノードで表しているので、ある程度属性として持たせられればグラフは簡素にできそうです。(するかどうかは別)