poi-plugin-compass 0.1.2 → 0.1.4
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/air-status.js +5 -5
- package/assets/compass.css +79 -48
- package/assets/icons/COPYRIGHT.md +7 -0
- package/assets/icons/spot/2.svg +37 -0
- package/assets/icons/spot/3.svg +37 -0
- package/assets/icons/spot/4-1.svg +37 -0
- package/assets/icons/spot/4-2.svg +37 -0
- package/assets/icons/spot/4-3.svg +8 -0
- package/assets/icons/spot/4-4.svg +30 -0
- package/assets/icons/spot/5.svg +50 -0
- package/assets/icons/spot/8.svg +56 -0
- package/assets/icons/spot/9.svg +37 -0
- package/data/maps.json +7 -13
- package/data/normal-maps.json +168 -154
- package/docs/research.md +7 -5
- package/docs/sources.md +1 -1
- package/index.js +382 -54
- package/logic.js +164 -15
- package/package.json +2 -2
package/logic.js
CHANGED
|
@@ -9,19 +9,20 @@ const SHIP_CATEGORIES = {
|
|
|
9
9
|
CL_ALL: new Set([3, 4, 21]),
|
|
10
10
|
CA: new Set([5]),
|
|
11
11
|
CAV: new Set([6]),
|
|
12
|
+
CA_ALL: new Set([5, 6]),
|
|
12
13
|
CVL: new Set([7]),
|
|
13
14
|
BB: new Set([8, 9]),
|
|
14
15
|
BBV: new Set([10]),
|
|
15
16
|
BB_ALL: new Set([8, 9, 10]),
|
|
16
|
-
CV: new Set([11, 12
|
|
17
|
-
CV_ALL: new Set([7, 11, 12
|
|
17
|
+
CV: new Set([11, 12]),
|
|
18
|
+
CV_ALL: new Set([7, 11, 12]),
|
|
18
19
|
SS: new Set([13, 14]),
|
|
19
20
|
AO: new Set([15]),
|
|
20
21
|
AV: new Set([16]),
|
|
21
22
|
LHA: new Set([17]),
|
|
22
23
|
AR: new Set([19]),
|
|
23
24
|
AS: new Set([20]),
|
|
24
|
-
CV_MAIN: new Set([11, 12
|
|
25
|
+
CV_MAIN: new Set([11, 12]),
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const CATEGORY_LABELS = {
|
|
@@ -33,6 +34,7 @@ const CATEGORY_LABELS = {
|
|
|
33
34
|
CL_ALL: 'CL系',
|
|
34
35
|
CA: '重巡',
|
|
35
36
|
CAV: '航巡',
|
|
37
|
+
CA_ALL: 'CA系',
|
|
36
38
|
CVL: '轻空母',
|
|
37
39
|
BB: '战舰(BB/FBB)',
|
|
38
40
|
BBV: '航战',
|
|
@@ -45,7 +47,7 @@ const CATEGORY_LABELS = {
|
|
|
45
47
|
LHA: '扬陆',
|
|
46
48
|
AR: '工作舰',
|
|
47
49
|
AS: '潜母',
|
|
48
|
-
CV_MAIN: '
|
|
50
|
+
CV_MAIN: 'CV/CVB',
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
const EQUIPMENT_CATEGORY_LABELS = {
|
|
@@ -313,17 +315,152 @@ function normalizeOutcomes(outcomes, rule = null, options = {}) {
|
|
|
313
315
|
: Number.isFinite(Number(outcome.probability)) ? Number(outcome.probability) : null,
|
|
314
316
|
}))
|
|
315
317
|
|
|
318
|
+
if (!normalized.length) return []
|
|
319
|
+
const hasKnownProbability = normalized.some((outcome) => outcome.probability != null)
|
|
316
320
|
const hasMissingProbability = normalized.some((outcome) => outcome.probability == null)
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
321
|
+
const allUnknown = !hasKnownProbability
|
|
322
|
+
if (rule?.continueOnFailure === true) {
|
|
323
|
+
if (!hasKnownProbability) {
|
|
324
|
+
// A rule such as “within this LOS range, go to N; if the check fails,
|
|
325
|
+
// continue below” has two effective branches. The source does not give
|
|
326
|
+
// a ratio, so expose the same temporary 50/50 estimate used by the
|
|
327
|
+
// route evaluator instead of showing an unhelpful “unknown” row.
|
|
328
|
+
const probability = 1 / (normalized.length + 1)
|
|
329
|
+
return normalized.map((outcome) => ({ to: outcome.to, probability, estimated: true }))
|
|
330
|
+
}
|
|
331
|
+
const estimated = rule.confidence === 'unknown' || rule.confidence === 'approximate'
|
|
332
|
+
return normalized
|
|
333
|
+
.filter((outcome) => outcome.probability != null)
|
|
334
|
+
.map((outcome) => ({
|
|
335
|
+
to: outcome.to,
|
|
336
|
+
probability: outcome.probability,
|
|
337
|
+
...(estimated ? { estimated: true } : {}),
|
|
338
|
+
}))
|
|
339
|
+
}
|
|
340
|
+
if (allUnknown && options.equalizeUnknown === false) {
|
|
341
|
+
return normalized.map((outcome) => ({ to: outcome.to, probability: null }))
|
|
342
|
+
}
|
|
343
|
+
const equalize = options.equalizeUnknown !== false && (
|
|
344
|
+
allUnknown || !hasMissingProbability && rule?.confidence === 'unknown'
|
|
345
|
+
)
|
|
346
|
+
const estimated = equalize || hasMissingProbability || rule?.confidence === 'unknown'
|
|
347
|
+
|| rule?.confidence === 'approximate' && normalized.length > 1
|
|
348
|
+
return normalized
|
|
349
|
+
.filter((outcome) => equalize || outcome.probability != null)
|
|
350
|
+
.map((outcome) => {
|
|
320
351
|
const normalizedOutcome = {
|
|
321
352
|
to: outcome.to,
|
|
322
353
|
probability: equalize && normalized.length ? 1 / normalized.length : outcome.probability,
|
|
323
354
|
}
|
|
324
355
|
if (estimated) normalizedOutcome.estimated = true
|
|
325
356
|
return normalizedOutcome
|
|
326
|
-
|
|
357
|
+
})
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function ruleDistribution(rule) {
|
|
361
|
+
const raw = (Array.isArray(rule?.outcomes) ? rule.outcomes : [])
|
|
362
|
+
.filter((outcome) => outcome && typeof outcome.to === 'string')
|
|
363
|
+
.map((outcome) => ({
|
|
364
|
+
to: outcome.to,
|
|
365
|
+
probability: outcome.probability == null
|
|
366
|
+
? null
|
|
367
|
+
: Number.isFinite(Number(outcome.probability)) ? Number(outcome.probability) : null,
|
|
368
|
+
}))
|
|
369
|
+
if (!raw.length) return { outcomes: [], residual: rule?.continueOnFailure === true ? 1 : 0 }
|
|
370
|
+
|
|
371
|
+
const known = raw.filter((outcome) => outcome.probability != null)
|
|
372
|
+
const knownTotal = known.reduce((total, outcome) => total + outcome.probability, 0)
|
|
373
|
+
const partial = rule?.continueOnFailure === true
|
|
374
|
+
|| (known.length > 0 && knownTotal < 1 - 1e-9)
|
|
375
|
+
|| (known.length > 0 && known.length < raw.length)
|
|
376
|
+
|
|
377
|
+
if (partial) {
|
|
378
|
+
if (known.length) {
|
|
379
|
+
return {
|
|
380
|
+
outcomes: normalizeOutcomes(raw, rule),
|
|
381
|
+
residual: Math.max(0, 1 - knownTotal),
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
const probability = 1 / (raw.length + 1)
|
|
385
|
+
return {
|
|
386
|
+
outcomes: raw.map((outcome) => ({ to: outcome.to, probability, estimated: true })),
|
|
387
|
+
residual: probability,
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return { outcomes: normalizeOutcomes(raw, rule), residual: 0 }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function evaluateRouteRules(mapDefinition, node, context) {
|
|
395
|
+
const rules = rulesForNode(mapDefinition, node)
|
|
396
|
+
if (!rules.length) {
|
|
397
|
+
return { status: 'terminal', rule: null, predicate: null, matchedRuleIds: [], outcomes: [], unknownProbability: 0 }
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const totals = new Map()
|
|
401
|
+
const matchedRuleIds = []
|
|
402
|
+
let residual = 1
|
|
403
|
+
let firstRule = null
|
|
404
|
+
let firstPredicate = null
|
|
405
|
+
let unresolvedPredicate = null
|
|
406
|
+
let terminal = false
|
|
407
|
+
|
|
408
|
+
function addOutcome(outcome, mass) {
|
|
409
|
+
if (!Number.isFinite(mass) || mass <= 0) return
|
|
410
|
+
const current = totals.get(outcome.to)
|
|
411
|
+
if (!current) {
|
|
412
|
+
totals.set(outcome.to, {
|
|
413
|
+
to: outcome.to,
|
|
414
|
+
probability: mass,
|
|
415
|
+
...(outcome.estimated === true ? { estimated: true } : {}),
|
|
416
|
+
})
|
|
417
|
+
return
|
|
418
|
+
}
|
|
419
|
+
current.probability += mass
|
|
420
|
+
if (outcome.estimated === true) current.estimated = true
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
for (const rule of rules) {
|
|
424
|
+
if (residual <= 1e-9) break
|
|
425
|
+
const predicate = evaluatePredicate(rule.predicate, context)
|
|
426
|
+
if (predicate.status === 'false') continue
|
|
427
|
+
if (predicate.status === 'unknown') {
|
|
428
|
+
unresolvedPredicate = { rule, predicate }
|
|
429
|
+
break
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (!firstRule) {
|
|
433
|
+
firstRule = rule
|
|
434
|
+
firstPredicate = predicate
|
|
435
|
+
}
|
|
436
|
+
if (rule.id) matchedRuleIds.push(rule.id)
|
|
437
|
+
if (rule.terminal === true) {
|
|
438
|
+
residual = 0
|
|
439
|
+
terminal = true
|
|
440
|
+
break
|
|
441
|
+
}
|
|
442
|
+
const distribution = ruleDistribution(rule)
|
|
443
|
+
if (!distribution.outcomes.length) {
|
|
444
|
+
unresolvedPredicate = { rule, predicate }
|
|
445
|
+
break
|
|
446
|
+
}
|
|
447
|
+
distribution.outcomes.forEach((outcome) => addOutcome(outcome, residual * outcome.probability))
|
|
448
|
+
residual *= distribution.residual
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const outcomes = [...totals.values()]
|
|
452
|
+
const unknownProbability = (unresolvedPredicate || residual > 1e-9) ? residual : 0
|
|
453
|
+
const status = unknownProbability > 1e-9
|
|
454
|
+
? 'unknown'
|
|
455
|
+
: outcomes.length ? 'matched' : terminal ? 'terminal' : 'unknown'
|
|
456
|
+
return {
|
|
457
|
+
status,
|
|
458
|
+
rule: firstRule || unresolvedPredicate?.rule || null,
|
|
459
|
+
predicate: firstPredicate || unresolvedPredicate?.predicate || null,
|
|
460
|
+
matchedRuleIds,
|
|
461
|
+
outcomes,
|
|
462
|
+
unknownProbability,
|
|
463
|
+
}
|
|
327
464
|
}
|
|
328
465
|
|
|
329
466
|
function routeDecision(mapDefinition, node, context, overrides = {}) {
|
|
@@ -334,9 +471,17 @@ function routeDecision(mapDefinition, node, context, overrides = {}) {
|
|
|
334
471
|
const manualOutcomes = Array.isArray(configuredManualOutcomes)
|
|
335
472
|
? normalizeOutcomes(configuredManualOutcomes, { confidence: 'unknown' }, { equalizeUnknown: false })
|
|
336
473
|
: null
|
|
337
|
-
const
|
|
338
|
-
?
|
|
339
|
-
|
|
474
|
+
const automatic = manual
|
|
475
|
+
? {
|
|
476
|
+
status: selected.status,
|
|
477
|
+
rule: selected.rule,
|
|
478
|
+
predicate: selected.predicate,
|
|
479
|
+
matchedRuleIds: selected.rule?.id ? [selected.rule.id] : [],
|
|
480
|
+
outcomes: selected.status === 'matched' ? normalizeOutcomes(selected.rule?.outcomes, selected.rule) : [],
|
|
481
|
+
unknownProbability: 0,
|
|
482
|
+
}
|
|
483
|
+
: evaluateRouteRules(mapDefinition, node, context)
|
|
484
|
+
const autoOutcomes = automatic.outcomes
|
|
340
485
|
const phaseRuleMatched = manual && hasPhaseRules(mapDefinition, node) && selected.status === 'matched'
|
|
341
486
|
const baseOutcomes = phaseRuleMatched
|
|
342
487
|
? autoOutcomes
|
|
@@ -349,9 +494,11 @@ function routeDecision(mapDefinition, node, context, overrides = {}) {
|
|
|
349
494
|
: baseOutcomes
|
|
350
495
|
return {
|
|
351
496
|
node,
|
|
352
|
-
status:
|
|
353
|
-
rule:
|
|
354
|
-
predicate:
|
|
497
|
+
status: automatic.status,
|
|
498
|
+
rule: automatic.rule,
|
|
499
|
+
predicate: automatic.predicate,
|
|
500
|
+
matchedRuleIds: automatic.matchedRuleIds,
|
|
501
|
+
unknownProbability: automatic.unknownProbability,
|
|
355
502
|
baseOutcomes,
|
|
356
503
|
manualOutcomes,
|
|
357
504
|
outcomes,
|
|
@@ -383,10 +530,12 @@ function propagateProbability(start, decisions) {
|
|
|
383
530
|
return
|
|
384
531
|
}
|
|
385
532
|
const decision = decisions[node]
|
|
386
|
-
if (!decision || decision.status === '
|
|
533
|
+
if (!decision || decision.status === 'terminal' && !decision.outcomes.length
|
|
534
|
+
|| decision.status === 'unknown' && !decision.outcomes.length) {
|
|
387
535
|
if (decision?.status === 'unknown') unknownNodes.add(node)
|
|
388
536
|
return
|
|
389
537
|
}
|
|
538
|
+
if (decision.status === 'unknown' || Number(decision.unknownProbability) > 1e-9) unknownNodes.add(node)
|
|
390
539
|
const nextPath = new Set(path)
|
|
391
540
|
nextPath.add(node)
|
|
392
541
|
decision.outcomes.forEach((outcome) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poi-plugin-compass",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "通常海域舰队罗盘",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"icon": "fa/compass",
|
|
53
53
|
"priority": 20,
|
|
54
54
|
"apiVer": {
|
|
55
|
-
"11.99.99": "0.1.
|
|
55
|
+
"11.99.99": "0.1.4"
|
|
56
56
|
}
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|