ダイアログ上に表示したNSBrowserで都道府県→都道府県別データを選択し、選択したデータの位置情報をMap Viewに表示するAppleScriptです。
# 2021年11月末にアーケードゲーム「戦場の絆」のサービスが終了したため、Webサイト側からデータ取得する部分の処理は動作しません(Webサイトごとアクセスできなくなったため)
▲macOS 10.12.6上で動作
「OK」ボタンをクリックすると選択したゲームセンターの諸元情報を返してきます。リスト一覧から名称を選択し、途中でその位置情報を地図で見られるという程度のインタフェースです。
NSBrowserを利用したUIの習作で、Web上の「戦場の絆」公式ページから導入店舗の情報を取得し(このあたりライブラリにまとめて部品化)、データを都道府県別にしぼりこんでNSBrowser上で選択できるようにしてみました。
▲macOS 10.13.6上で動作
▲macOS 10.14.4上で動作(Light Mode)
▲macOS 10.14.4上で動作(Dark Mode)
ぱっと見は「何かすごいもの」に見えるのですが、キーワード検索が実装されていないため、データしぼりこみに柔軟性がないと感じるものです。
NSBrowserをAppleScriptから利用した場合に、Xcodeを利用しないとこのレベルの単純なデータ階層固定でデータしぼりこみを行う程度のものしか作りにくいところでしょうか。不可能とは言わないものの、「普通にXcode上で作れば?」という話になると思います。
さらに、該当するカラムの行数を返すハンドラでデータをしぼりこんでレコード数を返しているものの、いまひとつここがうまく動いていない印象を受けます。NSBrowser上で「存在しないデータのような何か」をクリックできるケースがあり、それをクリックすると実行環境(スクリプトエディタとか、Script Debuggerとか)ごとクラッシュします。
→ 原因がわかりました。問題箇所も想像どおり。目下、修正版で謎のゴースト行も出てこなくなったので、あとで修正版を掲載しておきます。問題が2つあって、1つがPredicates文をas stringですべてcastしていなかった件、もうひとつは、、、副次的に発生した問題で、愛知県のデータに「M’s」という半角クォート文字を含むものがあって、これでPredicates文が中断されてしまった問題。半角シングルクォートを全角に置き換えるとかいろいろ手を加える必要がありました。
本Script全体をダウンロードして、スクリプトエディタ上で実行すると、最初に「戦場の絆」公式ホームページの日本国内の店舗情報をスキャンして店舗情報を抽出するため、サーバーの混雑具合やネットワーク回線速度にも左右されますが、自分の環境では5〜15秒程度でデータの取得が終了し、ダイアログが表示されます。
–> Download whole Script bundle with Library
AppleScript名:アラートダイアログ上にBrowser+Map Viewを表示.scptd |
— – Created by: Takaaki Naganoya – Created on: 2019/03/10 — – Copyright © 2019 Piyomaru Software, All Rights Reserved — use AppleScript version "2.4" — Yosemite (10.10) or later use framework "Foundation" use framework "AppKit" use framework "MapKit" use scripting additions use skLib : script "senjoNoKizunaLib" property NSView : a reference to current application’s NSView property NSAlert : a reference to current application’s NSAlert property NSColor : a reference to current application’s NSColor property NSBrowser : a reference to current application’s NSBrowser property MKMapView : a reference to current application’s MKMapView property NSScrollView : a reference to current application’s NSScrollView property NSMutableArray : a reference to current application’s NSMutableArray property MKMapTypeStandard : a reference to current application’s MKMapTypeStandard property NSRunningApplication : a reference to current application’s NSRunningApplication property NSAlertSecondButtonReturn : a reference to current application’s NSAlertSecondButtonReturn property zLevel : 17 property aMaxViewWidth : 1000 property aMaxViewHeight : 500 property theResult : 0 property returnCode : 0 property theDataSource : {} property aSelection : {} property aMapView : missing value property aBrowser : missing value property skDataList : {} property prefList : {"北海道", "青森県", "岩手県", "宮城県", "秋田県", "山形県", "福島県", "茨城県", "栃木県", "群馬県", "埼玉県", "千葉県", "東京都", "神奈川県", "新潟県", "富山県", "石川県", "福井県", "山梨県", "長野県", "岐阜県", "静岡県", "愛知県", "三重県", "滋賀県", "京都府", "大阪府", "兵庫県", "奈良県", "和歌山県", "鳥取県", "島根県", "岡山県", "広島県", "山口県", "徳島県", "香川県", "愛媛県", "高知県", "福岡県", "佐賀県", "長崎県", "熊本県", "大分県", "宮崎県", "鹿児島県", "沖縄県"} if my skDataList = {} then set my skDataList to current application’s NSMutableArray’s arrayWithArray:(getSenjoNokizunaGameCenterDataList() of skLib) end if set aSelection to {} set paramObj to {myMessage:"Choose a Game Center", mySubMessage:"Choose an appropriate Game Center from list to play Senjo-no-Kizuna"} my performSelectorOnMainThread:"chooseItemByBrowser:" withObject:(paramObj) waitUntilDone:true return my aSelection –> {loc_id:"QIEXj9er5QSA_Y42-OjPNg", gcName:"THE 3RD PLANET ジャングルパーク鹿児島", latitude:31.5703088, longitude:130.5653137, address:"鹿児島県 鹿児島市 与次郎 1-11-1 フレスポジャングルパーク2F"} on chooseItemByBrowser:paramObj set aMainMes to myMessage of paramObj set aSubMes to mySubMessage of paramObj — create a view set theView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aMaxViewWidth, aMaxViewHeight)) set aMapView to MKMapView’s alloc()’s initWithFrame:(current application’s NSMakeRect(410, 0, aMaxViewWidth – 410, aMaxViewHeight)) tell aMapView its setMapType:(MKMapTypeStandard) its setZoomEnabled:true its setScrollEnabled:true its setPitchEnabled:true its setRotateEnabled:true its setShowsCompass:true its setShowsZoomControls:true its setShowsScale:true its setShowsUserLocation:true its setDelegate:me end tell — make browser view with scroll view set aScrollWithTable to makeBrowserView(prefList, 400, aMaxViewHeight) of me –Compose Views in NSView theView’s setSubviews:{aScrollWithTable, aMapView} — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:aMainMes its setInformativeText:aSubMes its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:theView end tell — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true if (my returnCode as number) = 1001 then error number -128 end chooseItemByBrowser: on doModal:aParam set (my returnCode) to aParam’s runModal() end doModal: on makeBrowserView(aList as list, aWidth as number, aHeight as number) set (my theDataSource) to NSMutableArray’s arrayWithArray:aList set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) set aBrowser to NSBrowser’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight)) aBrowser’s setDelegate:(me) aBrowser’s setTarget:(me) aBrowser’s setAction:"browserCellSelected:" aBrowser’s setMinColumnWidth:120 aBrowser’s setSeparatesColumns:true aBrowser’s setMaxVisibleColumns:2 aBrowser’s setAutohidesScroller:true aBrowser’s setTakesTitleFromPreviousColumn:true –aBrowser’s setBackgroundColor:(NSColor’s grayColor()) aScroll’s setDocumentView:aBrowser aBrowser’s enclosingScrollView()’s setHasHorizontalScroller:true aBrowser’s enclosingScrollView()’s setHasVerticalScroller:true return aScroll end makeBrowserView –NSBrowser Event Handlers –ここ、いまひとつきちんと動いていないかも??? on browser:aView numberOfRowsInColumn:aColumn if aColumn = 0 then return my theDataSource’s |count|() else if aColumn = 1 then set aPath to text 2 thru -1 of ((aView’s |path|()) as string) set tmpArray to (my filterRecListByLabel1(skDataList, "address BEGINSWITH ’" & aPath & "’")) as list return (length of tmpArray) end if end browser:numberOfRowsInColumn: on browser:aView willDisplayCell:(aCell) atRow:(rowIndex as integer) column:(colIndex as integer) if colIndex = 0 then –Prefectures aCell’s setTitle:((item (rowIndex + 1) of prefList) as string) aCell’s setLeaf:false else if colIndex = 1 then –Each Game Centers in the Prefecture set aPath to text 2 thru -1 of ((aView’s |path|()) as string) set tmpArray to my filterRecListByLabel1(skDataList, "address BEGINSWITH ’" & aPath & "’") set tmpItem to (tmpArray’s objectAtIndex:rowIndex) set aGameCenterName to (tmpItem’s gcName) as string aCell’s setTitle:(aGameCenterName) aCell’s setLeaf:true end if end browser:willDisplayCell:atRow:column: on browserCellSelected:aSender set aPath to my aBrowser’s |path|() set aList to (aPath’s pathComponents()) as list set aLen to length of aList if aLen = 3 then –set aPref to contents of item 2 of aList set aGc to contents of last item of aList set tmpArray to my filterRecListByLabel1(skDataList, "gcName == ’" & aGc & "’") set tmpItem to contents of first item of (tmpArray as list) copy tmpItem to my aSelection set aLatitude to (latitude of tmpItem) as real set aLongitude to (longitude of tmpItem) as real tell aMapView set aLocation to current application’s CLLocationCoordinate2DMake(aLatitude, aLongitude) its setCenterCoordinate:aLocation zoomLevel:(zLevel) animated:false end tell end if end browserCellSelected: –NSArrayに入れたNSDictionaryを、指定の属性ラベルの値で抽出 on filterRecListByLabel1(aRecList, aPredicate as string) set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate set filteredArray to aRecList’s filteredArrayUsingPredicate:aPredicate return filteredArray end filterRecListByLabel1 |