splatone 0.0.12 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,10 @@ SNSのジオタグ付きポストをキーワードに基づいて収集する
13
13
 
14
14
  ## Change Log
15
15
 
16
+ ### v0.0.12 → v0.0.13
17
+ * BulkyのPointMarkerのサイズや透明度を可変に
18
+ * コマンドライン引数で指定 (詳しくは``` npx -y -- splatone@latest crawler --help```)
19
+
16
20
  ### v0.0.11 → v0.0.12
17
21
 
18
22
  * Bottleneckを導入しクエリ間隔を適正値に調整 (3 queries/ 3 sec.)
@@ -54,40 +58,49 @@ $ npx -y -- splatone@latest crawler --help
54
58
  使い方: crawler.js [options]
55
59
 
56
60
  Basic Options
57
- -p, --plugin 実行するプラグイン[文字列] [必須] [選択してください: "flickr"]
58
- -o, --options プラグインオプション [文字列] [デフォルト: "{}"]
59
- -k, --keywords 検索キーワード(|区切り) [文字列] [デフォルト:
60
- "nature,tree,flower|building,house|water,sea,river,pond"]
61
+ -p, --plugin 実行するプラグイン[文字列] [必須] [選択してください: "flickr"]
62
+ -o, --options プラグインオプション [文字列] [デフォルト: "{}"]
63
+ -k, --keywords 検索キーワード(|区切り) [文字列] [デフォルト:
64
+ "nature,tree,flower|building,house|water,sea,river,pond"]
61
65
  -f, --filed 大きなデータをファイルとして送受信する
62
- [真偽] [デフォルト: true]
66
+ [真偽] [デフォルト: true]
63
67
  -c, --chopped 大きなデータを細分化して送受信する
64
- [非推奨] [真偽] [デフォルト: false]
68
+ [非推奨] [真偽] [デフォルト: false]
65
69
 
66
70
  Debug
67
- --debug-verbose デバッグ情報出力 [真偽] [デフォルト: false]
71
+ --debug-verbose デバッグ情報出力 [真偽] [デフォルト: false]
68
72
 
69
73
  For flickr Plugin
70
- --p-flickr-APIKEY Flickr ServiceのAPI KEY [文字列]
71
- --p-flickr-Extras カンマ区切り/保持する写真のメタデータ(デフォルト値は
74
+ --p-flickr-APIKEY Flickr ServiceのAPI KEY [文字列]
75
+ --p-flickr-Extras カンマ区切り/保持する写真のメタデータ(デフォルト値は
72
76
  記載の有無に関わらず保持)
73
- [文字列] [デフォルト: "date_upload,date_taken,owner_name,geo,url_s,tags"]
74
- --p-flickr-DateMode 利用時間軸(update=Flickr投稿日時/taken=写真撮影日時)
75
- [選択してください: "upload", "taken"] [デフォルト: "upload"]
76
- --p-flickr-Haste 時間軸分割並列処理 [真偽] [デフォルト: true]
77
- --p-flickr-DateMax クローリング期間(最大) UNIX TIMEもしくはYYYY-MM-DD
78
- [文字列] [デフォルト: 1762904780]
79
- --p-flickr-DateMin クローリング期間(最小) UNIX TIMEもしくはYYYY-MM-DD
80
- [文字列] [デフォルト: 1072882800]
77
+ [文字列] [デフォルト: "date_upload,date_taken,owner_name,geo,url_s,tags"]
78
+ --p-flickr-DateMode 利用時間軸(update=Flickr投稿日時/taken=写真撮影日時)
79
+ [選択してください: "upload", "taken"] [デフォルト: "upload"]
80
+ --p-flickr-Haste 時間軸分割並列処理 [真偽] [デフォルト: true]
81
+ --p-flickr-DateMax クローリング期間(最大) UNIX TIMEもしくはYYYY-MM-DD
82
+ [文字列] [デフォルト: 1762942310]
83
+ --p-flickr-DateMin クローリング期間(最小) UNIX TIMEもしくはYYYY-MM-DD
84
+ [文字列] [デフォルト: 1072882800]
81
85
 
82
86
  Visualization (最低一つの指定が必須です)
83
87
  --vis-bulky 全データをCircleMarkerとして地図上に表示
84
- [真偽] [デフォルト: false]
88
+ [真偽] [デフォルト: false]
85
89
  --vis-marker-cluster マーカークラスターとして地図上に表示
86
- [真偽] [デフォルト: false]
90
+ [真偽] [デフォルト: false]
91
+
92
+ For bulky Visualizer
93
+ --v-bulky-Radius Point Markerの直径 [数値] [デフォルト: 5]
94
+ --v-bulky-Stroke Point Markerの線の有無 [真偽] [デフォルト: true]
95
+ --v-bulky-Weight Point Markerの線の太さ [数値] [デフォルト: 1]
96
+ --v-bulky-Opacity Point Markerの線の透明度 [数値] [デフォルト: 1]
97
+ --v-bulky-Filling Point Markerの塗りの有無 [真偽] [デフォルト: true]
98
+ --v-bulky-FillOpacity Point Markerの塗りの透明度 [数値] [デフォルト: 0.5]
87
99
 
88
100
  オプション:
89
- --help ヘルプを表示 [真偽]
90
- --version バージョンを表示 [真偽]
101
+ --help ヘルプを表示 [真偽]
102
+ --version バージョンを表示 [真偽]
103
+
91
104
  ```
92
105
  ## クローリングの実行
93
106
 
package/crawler.js CHANGED
@@ -30,7 +30,7 @@ import { hideBin } from 'yargs/helpers';
30
30
  // -------------------------------
31
31
  import { loadPlugins } from './lib/pluginLoader.js';
32
32
  import paletteGenerator from './lib/paletteGenerator.js';
33
- import { dfsObject, bboxSize, saveGeoJsonObjectAsStream, buildPluginsOptions, loadAPIKey } from '#lib/splatone';
33
+ import { dfsObject, bboxSize, saveGeoJsonObjectAsStream, buildPluginsOptions, loadAPIKey, buildVisualizersOptions } from '#lib/splatone';
34
34
 
35
35
  const __filename = fileURLToPath(import.meta.url);
36
36
  const __dirname = dirname(__filename);
@@ -39,6 +39,8 @@ const app = express();
39
39
  const port = 3000;
40
40
  const title = 'Splatone - Multi-Layer Composite Heatmap Viewer';
41
41
  let pluginsOptions = {};
42
+ let visOptions = {};
43
+
42
44
  const flickrLimiter = new Bottleneck({
43
45
  maxConcurrent: 5,
44
46
  minTime: 350, // 約3req/sec
@@ -58,6 +60,7 @@ try {
58
60
  api,
59
61
  optionsById: {},
60
62
  });
63
+
61
64
  // Visualizer読み込み
62
65
  const all_visualizers = {}; // { [name: string]: class }
63
66
  // クラス判定の小ヘルパ
@@ -178,14 +181,20 @@ try {
178
181
  plugins.list().forEach(async (plug) => {
179
182
  yargv = await plugins.call(plug, "yargv", yargv);
180
183
  })
181
- Object.keys(all_visualizers).forEach((vis) => {
184
+
185
+
186
+ const visualizers_ = {};
187
+ await Object.keys(all_visualizers).forEach(async (vis) => {
182
188
  yargv = yargv.option('vis-' + vis, {
183
189
  group: 'Visualization (最低一つの指定が必須です)',
184
190
  type: 'boolean',
185
191
  default: false,
186
192
  description: all_visualizers[vis].description
187
193
  })
194
+ visualizers_[vis] = new all_visualizers[vis]();
195
+ yargv = await visualizers_[vis].yargv(yargv);
188
196
  });
197
+
189
198
  yargv = yargv.check(async (argv, options) => {
190
199
  if (Object.keys(all_visualizers).filter(v => argv["vis-" + v]).length == 0) {
191
200
  throw new Error('可視化ツールの指定がありません。最低一つは指定してください。');
@@ -194,7 +203,9 @@ try {
194
203
  console.warn("--filedと--choppedが両方指定されています。--filedが優先されます。");
195
204
  argv.chopped = false;
196
205
  }
197
- pluginsOptions = buildPluginsOptions(argv, plugins.list())
206
+ pluginsOptions = buildPluginsOptions(argv, plugins.list());
207
+ visOptions = buildVisualizersOptions(argv, Object.keys(visualizers_));
208
+ //console.log(visOptions);
198
209
  pluginsOptions[argv.plugin] = await plugins.call(argv.plugin, 'check', pluginsOptions[argv.plugin]);
199
210
  return true;
200
211
  });
@@ -202,20 +213,10 @@ try {
202
213
  const argv = await yargv.parseAsync();
203
214
 
204
215
  const visualizers = {};
205
- for (const vis of Object.keys(all_visualizers).filter(v => argv[`vis-${v}`])) {
206
- visualizers[vis] = new all_visualizers[vis]();
216
+ for (const vis of Object.keys(visualizers_).filter(v => argv[`vis-${v}`])) {
217
+ visualizers[vis] = visualizers_[vis];
207
218
  }
208
219
 
209
- /* const plugin_options = argv.options?.[argv.plugin] ?? {}
210
- try {
211
- plugin_options.API_KEY = await loadAPIKey("flickr") ?? plugin_options.API_KEY;
212
- } catch (e) {
213
- if (!plugin_options.API_KEY) {
214
- console.error("Error loading API key:", e.message);
215
- }
216
- //Nothing to do
217
- }*/
218
- //pluginsOptions = buildPluginsOptions(argv, plugins.list());
219
220
  await plugins.call(argv.plugin, 'init', pluginsOptions[argv.plugin]);
220
221
  if (argv.debugVerbose) {
221
222
  console.table([["Visualizer", Object.keys(visualizers)], ["Plugin", argv.plugin]]);
@@ -225,6 +226,7 @@ try {
225
226
  const processing = {};
226
227
  const crawlers = {};
227
228
  const targets = {};
229
+
228
230
  // 初期中心(凱旋門)
229
231
  const DEFAULT_CENTER = { lat: 48.873611, lon: 2.294444 };
230
232
 
@@ -633,7 +635,8 @@ try {
633
635
  const resultId = uniqid();
634
636
  const result = crawlers[currentSessionId];
635
637
  const target = targets[currentSessionId];
636
- let geoJson = Object.fromEntries(Object.entries(visualizers).map(([vis, v]) => [vis, v.getFutureCollection(result, target)]));
638
+
639
+ let geoJson = Object.fromEntries(Object.entries(visualizers).map(([vis, v]) => [vis, v.getFutureCollection(result, target, visOptions[vis])]));
637
640
 
638
641
  //console.log('[splatone:finish]');
639
642
  try {
@@ -645,7 +648,8 @@ try {
645
648
  geoJson,
646
649
  palette: target["splatonePalette"],
647
650
  visualizers: Object.keys(visualizers),
648
- plugin: argv.plugin
651
+ plugin: argv.plugin,
652
+ visOptions
649
653
  });
650
654
  } catch (e) {
651
655
  if (e instanceof RangeError && /Invalid string length/.test(String(e.message))) {
@@ -719,7 +723,8 @@ try {
719
723
  geoJson: null, /*geoJsonは送らない*/
720
724
  palette: target["splatonePalette"],
721
725
  visualizers: Object.keys(visualizers),
722
- plugin: argv.plugin
726
+ plugin: argv.plugin,
727
+ visOptions
723
728
  });
724
729
  console.log("[Done]");
725
730
  } else {
package/lib/PluginBase.js CHANGED
@@ -16,9 +16,12 @@ export class PluginBase {
16
16
  argKey(key) {
17
17
  return "p-" + this.id + "-" + key;
18
18
  }
19
+ async yargv(yargv) {
20
+ return yargv;
21
+ }
19
22
  async check(option) {
20
23
  //throw Error("Plugin Option Error!");
21
- return true;
24
+ return options;
22
25
  }
23
26
 
24
27
  async init(options = {}) {
@@ -9,7 +9,17 @@ export class VisualizerBase {
9
9
  /** @param {object} api - ホストが提供する能力(権限を最小化) */
10
10
  constructor() {
11
11
  }
12
- async init() {}
13
- async start() {}
14
- async stop() {}
12
+ argKey(key) {
13
+ return "v-" + this.id + "-" + key;
14
+ }
15
+ async yargv(yargv) {
16
+ return yargv;
17
+ }
18
+ async check(option) {
19
+ //throw Error("Plugin Option Error!");
20
+ return options;
21
+ }
22
+ async init() { }
23
+ async start() { }
24
+ async stop() { }
15
25
  }
package/lib/splatone.js CHANGED
@@ -160,10 +160,17 @@ export async function saveGeoJsonObjectAsStream(geoJsonObject, outfile) {
160
160
  return destPath;
161
161
  }
162
162
 
163
+ export function buildVisualizersOptions(argv, visualizerIds) {
164
+ return buildOptions('v', argv, visualizerIds);
165
+ }
163
166
  export function buildPluginsOptions(argv, pluginIds) {
167
+ return buildOptions('p', argv, pluginIds);
168
+ }
169
+
170
+ function buildOptions(context, argv, ids) {
164
171
  const out = {};
165
- for (const id of pluginIds) {
166
- const prefix = `p-${id}`;
172
+ for (const id of ids) {
173
+ const prefix = `${context}-${id}`;
167
174
  const opts = {};
168
175
  for (const [key, val] of Object.entries(argv)) {
169
176
  if (key === '_' || key === '$0') continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "splatone",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "Multi-layer Composite Heatmap",
5
5
  "homepage": "https://github.com/YokoyamaLab/Splatone#readme",
6
6
  "bugs": {
package/views/index.ejs CHANGED
@@ -337,7 +337,8 @@
337
337
  };
338
338
  for (const vis in visualizers) {
339
339
  const layers = await visualizers[vis](map, res.geoJson[vis], {
340
- palette: res.palette
340
+ palette: res.palette,
341
+ visOptions:res.visOptions[vis]
341
342
  });
342
343
  //console.log("【レイヤ】\n", JSON.stringify(layers,null,4));
343
344
  if ((layers == null)) {
@@ -1,18 +1,54 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
1
3
  import { VisualizerBase } from '../../lib/VisualizerBase.js';
2
4
  import { featureCollection } from "@turf/turf";
3
5
 
4
6
  export default class BulkyVisualizer extends VisualizerBase {
5
- static id = 'bulky'; // 一意ID(フォルダ名と一致させると運用しやすい)
6
7
  static name = 'Bulky Visualizer'; // 表示名
7
8
  static version = '0.0.0';
8
9
  static description = "全データをCircleMarkerとして地図上に表示";
9
10
 
10
11
  constructor() {
11
12
  super();
13
+ this.id = path.basename(path.dirname(fileURLToPath(import.meta.url)));//必須(ディレクトリ名がビジュアライザ名)
14
+ }
15
+ async yargv(yargv) {
16
+ // 必須項目にすると、このプラグインを使用しない時も必須になります。
17
+ // 必須項目は作らず、もしプラグインを使う上での制約違反はinitで例外を投げてください。
18
+ return yargv.option(this.argKey('Radius'), {
19
+ group: 'For ' + this.id + ' Visualizer',
20
+ type: 'number',
21
+ description: 'Point Markerの直径',
22
+ default: 5
23
+ }).option(this.argKey('Stroke'), {
24
+ group: 'For ' + this.id + ' Visualizer',
25
+ type: 'boolean',
26
+ description: 'Point Markerの線の有無',
27
+ default: true
28
+ }).option(this.argKey('Weight'), {
29
+ group: 'For ' + this.id + ' Visualizer',
30
+ type: 'number',
31
+ description: 'Point Markerの線の太さ',
32
+ default: 1
33
+ }).option(this.argKey('Opacity'), {
34
+ group: 'For ' + this.id + ' Visualizer',
35
+ type: 'number',
36
+ description: 'Point Markerの線の透明度',
37
+ default: 1
38
+ }).option(this.argKey('Filling'), {
39
+ group: 'For ' + this.id + ' Visualizer',
40
+ type: 'boolean',
41
+ description: 'Point Markerの塗りの有無',
42
+ default: true
43
+ }).option(this.argKey('FillOpacity'), {
44
+ group: 'For ' + this.id + ' Visualizer',
45
+ type: 'number',
46
+ description: 'Point Markerの塗りの透明度',
47
+ default: .5
48
+ });
12
49
  }
13
50
 
14
- getFutureCollection(result, target){
15
- //console.log(JSON.stringify(target, null, 4));
51
+ getFutureCollection(result, target, visOptions) {
16
52
  const layers = {};
17
53
  for (const hex in result) {
18
54
  for (const cat in result[hex]) {
@@ -20,17 +56,17 @@ export default class BulkyVisualizer extends VisualizerBase {
20
56
  layers[cat] = [];
21
57
  }
22
58
  for (const feature of result[hex][cat].items.features) {
23
- feature.properties["radius"] = 5;
59
+ feature.properties["radius"] = visOptions.Radius;
24
60
 
25
- feature.properties["stroke"] = true;
26
- feature.properties["color"] = target.splatonePalette[cat].darken;
27
- feature.properties["weight"] = 1;
28
- feature.properties["opacity"] = 1;
61
+ feature.properties["stroke"] = visOptions.Stroke;
62
+ feature.properties["color"] = target.splatonePalette[cat].darken;
63
+ feature.properties["weight"] = visOptions.Weight;
64
+ feature.properties["opacity"] = visOptions.Opacity;
29
65
 
30
- feature.properties["fill"] = true;
66
+ feature.properties["fill"] = visOptions.Filling;
31
67
  feature.properties["fillColor"] = target.splatonePalette[cat].color;
32
- feature.properties["fillOpacity"] = .5;
33
-
68
+ feature.properties["fillOpacity"] = visOptions.FillOpacity;
69
+
34
70
  layers[cat].push(feature);
35
71
  }
36
72
  }
@@ -1,6 +1,7 @@
1
1
  let booted = false;
2
2
  export default async function main(map, geojson, options = {}) {
3
3
  //console.log("main");
4
+ console.log("[VIS OPTIONS]",options.visOptions);
4
5
  if (booted) return;
5
6
  booted = true;
6
7
  const layers = {};
@@ -1,3 +1,5 @@
1
+ import path from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
1
3
  import { VisualizerBase } from '../../lib/VisualizerBase.js';
2
4
  import { featureCollection } from "@turf/turf";
3
5
 
@@ -10,8 +12,10 @@ export default class MarkerClusterVisualizer extends VisualizerBase {
10
12
 
11
13
  constructor() {
12
14
  super();
15
+ this.id = path.basename(path.dirname(fileURLToPath(import.meta.url)));//必須(ディレクトリ名がビジュアライザ名)
13
16
  }
14
17
 
18
+
15
19
  concatFC(fcA, fcB) {
16
20
  return {
17
21
  type: "FeatureCollection",
@@ -31,7 +35,7 @@ export default class MarkerClusterVisualizer extends VisualizerBase {
31
35
  });
32
36
  return { type: "FeatureCollection", features };
33
37
  }
34
- getFutureCollection(result, target) {
38
+ getFutureCollection(result, target, visOptions) {
35
39
  //console.log(JSON.stringify(target, null, 4));
36
40
  const layers = {};
37
41
  for (const hex in result) {
@@ -1,8 +1,10 @@
1
1
  let booted = false;
2
- export default async function main(map, geojson, options = { palette: {} }) {
2
+ export default async function main(map, geojson, options = { palette: {}, visOptions: {} }) {
3
3
  if (booted) return;
4
4
  booted = true;
5
5
 
6
+ console.log("[VIS OPTIONS]",options.visOptions);
7
+
6
8
  const urls = [
7
9
  'https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css',
8
10
  'https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css',