@jjlmoya/utils-forensic-science 1.3.0 → 1.5.0

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.
Files changed (59) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +5 -1
  3. package/src/entries.ts +9 -1
  4. package/src/index.ts +2 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/tool_validation.test.ts +2 -2
  7. package/src/tool/fire-pattern-origin-analyzer/bibliography.astro +6 -0
  8. package/src/tool/fire-pattern-origin-analyzer/bibliography.ts +12 -0
  9. package/src/tool/fire-pattern-origin-analyzer/component.astro +196 -0
  10. package/src/tool/fire-pattern-origin-analyzer/entry.ts +32 -0
  11. package/src/tool/fire-pattern-origin-analyzer/fire-pattern-origin-analyzer.css +681 -0
  12. package/src/tool/fire-pattern-origin-analyzer/i18n/de.ts +250 -0
  13. package/src/tool/fire-pattern-origin-analyzer/i18n/en.ts +250 -0
  14. package/src/tool/fire-pattern-origin-analyzer/i18n/es.ts +250 -0
  15. package/src/tool/fire-pattern-origin-analyzer/i18n/fr.ts +250 -0
  16. package/src/tool/fire-pattern-origin-analyzer/i18n/id.ts +250 -0
  17. package/src/tool/fire-pattern-origin-analyzer/i18n/it.ts +250 -0
  18. package/src/tool/fire-pattern-origin-analyzer/i18n/ja.ts +250 -0
  19. package/src/tool/fire-pattern-origin-analyzer/i18n/ko.ts +250 -0
  20. package/src/tool/fire-pattern-origin-analyzer/i18n/nl.ts +250 -0
  21. package/src/tool/fire-pattern-origin-analyzer/i18n/pl.ts +250 -0
  22. package/src/tool/fire-pattern-origin-analyzer/i18n/pt.ts +250 -0
  23. package/src/tool/fire-pattern-origin-analyzer/i18n/ru.ts +250 -0
  24. package/src/tool/fire-pattern-origin-analyzer/i18n/sv.ts +250 -0
  25. package/src/tool/fire-pattern-origin-analyzer/i18n/tr.ts +250 -0
  26. package/src/tool/fire-pattern-origin-analyzer/i18n/zh.ts +246 -0
  27. package/src/tool/fire-pattern-origin-analyzer/index.ts +11 -0
  28. package/src/tool/fire-pattern-origin-analyzer/logic.ts +123 -0
  29. package/src/tool/fire-pattern-origin-analyzer/render.ts +159 -0
  30. package/src/tool/fire-pattern-origin-analyzer/seo.astro +15 -0
  31. package/src/tool/fire-pattern-origin-analyzer/view-bindings.ts +171 -0
  32. package/src/tool/fire-pattern-origin-analyzer/view-model.ts +244 -0
  33. package/src/tool/fire-pattern-origin-analyzer/view.ts +30 -0
  34. package/src/tool/forensic-fingerprint-minutiae-identifier/bibliography.astro +6 -0
  35. package/src/tool/forensic-fingerprint-minutiae-identifier/bibliography.ts +16 -0
  36. package/src/tool/forensic-fingerprint-minutiae-identifier/component.astro +429 -0
  37. package/src/tool/forensic-fingerprint-minutiae-identifier/drawer.ts +94 -0
  38. package/src/tool/forensic-fingerprint-minutiae-identifier/entry.ts +32 -0
  39. package/src/tool/forensic-fingerprint-minutiae-identifier/forensic-fingerprint-minutiae-identifier.css +969 -0
  40. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/de.ts +298 -0
  41. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/en.ts +289 -0
  42. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/es.ts +291 -0
  43. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/fr.ts +298 -0
  44. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/id.ts +298 -0
  45. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/it.ts +298 -0
  46. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/ja.ts +281 -0
  47. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/ko.ts +281 -0
  48. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/nl.ts +298 -0
  49. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/pl.ts +298 -0
  50. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/pt.ts +298 -0
  51. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/ru.ts +298 -0
  52. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/sv.ts +298 -0
  53. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/tr.ts +298 -0
  54. package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/zh.ts +281 -0
  55. package/src/tool/forensic-fingerprint-minutiae-identifier/index.ts +11 -0
  56. package/src/tool/forensic-fingerprint-minutiae-identifier/logic.ts +168 -0
  57. package/src/tool/forensic-fingerprint-minutiae-identifier/renderer.ts +116 -0
  58. package/src/tool/forensic-fingerprint-minutiae-identifier/seo.astro +15 -0
  59. package/src/tools.ts +5 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-forensic-science",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -11,6 +11,8 @@ import { forensicMicrocrystalDrugSimulator } from '../tool/forensic-microcrystal
11
11
  import { forensicGlassBeckeLineSimulator } from '../tool/forensic-glass-becke-line-simulator/index';
12
12
  import { forensicFiberComparisonMicroscope } from '../tool/forensic-fiber-comparison-microscope/index';
13
13
  import { bloodstainPatternOriginAnalyzer } from '../tool/bloodstain-pattern-origin-analyzer/index';
14
+ import { forensicFingerprintMinutiaeIdentifier } from '../tool/forensic-fingerprint-minutiae-identifier/index';
15
+ import { firePatternOriginAnalyzer } from '../tool/fire-pattern-origin-analyzer/index';
14
16
 
15
17
  export const forensicCategory: ScienceCategoryEntry = {
16
18
  icon: 'mdi:fingerprint',
@@ -26,7 +28,9 @@ export const forensicCategory: ScienceCategoryEntry = {
26
28
  forensicMicrocrystalDrugSimulator,
27
29
  forensicGlassBeckeLineSimulator,
28
30
  forensicFiberComparisonMicroscope,
29
- bloodstainPatternOriginAnalyzer
31
+ bloodstainPatternOriginAnalyzer,
32
+ forensicFingerprintMinutiaeIdentifier,
33
+ firePatternOriginAnalyzer
30
34
  ],
31
35
  i18n: {
32
36
  de: () => import('./i18n/de').then((m) => m.content),
package/src/entries.ts CHANGED
@@ -22,6 +22,10 @@ export { forensicFiberComparisonMicroscope } from './tool/forensic-fiber-compari
22
22
  export type { FiberComparisonMicroscopeUI, FiberComparisonMicroscopeLocaleContent } from './tool/forensic-fiber-comparison-microscope/entry';
23
23
  export { bloodstainPatternOriginAnalyzer } from './tool/bloodstain-pattern-origin-analyzer/entry';
24
24
  export type { BloodstainPatternUI, BloodstainPatternLocaleContent } from './tool/bloodstain-pattern-origin-analyzer/entry';
25
+ export { forensicFingerprintMinutiaeIdentifier } from './tool/forensic-fingerprint-minutiae-identifier/entry';
26
+ export type { FingerprintMinutiaeUI, FingerprintMinutiaeLocaleContent } from './tool/forensic-fingerprint-minutiae-identifier/entry';
27
+ export { firePatternOriginAnalyzer } from './tool/fire-pattern-origin-analyzer/entry';
28
+ export type { FirePatternOriginAnalyzerUI, FirePatternOriginAnalyzerLocaleContent } from './tool/fire-pattern-origin-analyzer/entry';
25
29
 
26
30
  import { forensicAgeEstimator } from './tool/forensic-age-estimator/entry';
27
31
  import { widmarkAlcoholSimulator } from './tool/widmark-alcohol-simulator/entry';
@@ -35,6 +39,8 @@ import { forensicMicrocrystalDrugSimulator } from './tool/forensic-microcrystal-
35
39
  import { forensicGlassBeckeLineSimulator } from './tool/forensic-glass-becke-line-simulator/entry';
36
40
  import { forensicFiberComparisonMicroscope } from './tool/forensic-fiber-comparison-microscope/entry';
37
41
  import { bloodstainPatternOriginAnalyzer } from './tool/bloodstain-pattern-origin-analyzer/entry';
42
+ import { forensicFingerprintMinutiaeIdentifier } from './tool/forensic-fingerprint-minutiae-identifier/entry';
43
+ import { firePatternOriginAnalyzer } from './tool/fire-pattern-origin-analyzer/entry';
38
44
 
39
45
  export const ALL_ENTRIES = [
40
46
  forensicAgeEstimator,
@@ -48,5 +54,7 @@ export const ALL_ENTRIES = [
48
54
  forensicMicrocrystalDrugSimulator,
49
55
  forensicGlassBeckeLineSimulator,
50
56
  forensicFiberComparisonMicroscope,
51
- bloodstainPatternOriginAnalyzer
57
+ bloodstainPatternOriginAnalyzer,
58
+ forensicFingerprintMinutiaeIdentifier,
59
+ firePatternOriginAnalyzer
52
60
  ];
package/src/index.ts CHANGED
@@ -12,6 +12,8 @@ export { FORENSIC_MICROCRYSTAL_DRUG_SIMULATOR_TOOL } from './tool/forensic-micro
12
12
  export { FORENSIC_GLASS_BECKE_LINE_SIMULATOR_TOOL } from './tool/forensic-glass-becke-line-simulator/index';
13
13
  export { FORENSIC_FIBER_COMPARISON_MICROSCOPE_TOOL } from './tool/forensic-fiber-comparison-microscope/index';
14
14
  export { BLOODSTAIN_PATTERN_ORIGIN_ANALYZER_TOOL } from './tool/bloodstain-pattern-origin-analyzer/index';
15
+ export { FORENSIC_FINGERPRINT_MINUTIAE_IDENTIFIER_TOOL } from './tool/forensic-fingerprint-minutiae-identifier/index';
16
+ export { FIRE_PATTERN_ORIGIN_ANALYZER_TOOL } from './tool/fire-pattern-origin-analyzer/index';
15
17
 
16
18
  export type {
17
19
  KnownLocale,
@@ -18,7 +18,7 @@ describe('Locale Completeness Validation', () => {
18
18
  });
19
19
  });
20
20
 
21
- it('all 12 tools registered', () => {
22
- expect(ALL_TOOLS.length).toBe(12);
21
+ it('all 14 tools registered', () => {
22
+ expect(ALL_TOOLS.length).toBe(14);
23
23
  });
24
24
  });
@@ -4,8 +4,8 @@ import { scienceCategory } from '../data';
4
4
 
5
5
  describe('Tool Validation Suite', () => {
6
6
  describe('Library Registration', () => {
7
- it('should have 12 tools in ALL_TOOLS', () => {
8
- expect(ALL_TOOLS.length).toBe(12);
7
+ it('should have 14 tools in ALL_TOOLS', () => {
8
+ expect(ALL_TOOLS.length).toBe(14);
9
9
  });
10
10
 
11
11
  it('scienceCategory should be defined', () => {
@@ -0,0 +1,6 @@
1
+ ---
2
+ import { Bibliography as BibliographyRenderer } from '@jjlmoya/utils-shared';
3
+ import { bibliography } from './bibliography';
4
+ ---
5
+
6
+ <BibliographyRenderer links={bibliography} />
@@ -0,0 +1,12 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: 'NFPA 921: Guide for Fire and Explosion Investigations.',
6
+ url: 'https://www.nfpa.org/codes-and-standards/nfpa-921-standard-development/921',
7
+ },
8
+ {
9
+ name: 'NIJ: Fire and Arson Scene Evidence, A Guide for Public Safety Personnel.',
10
+ url: 'https://www.ojp.gov/pdffiles1/nij/181584.pdf',
11
+ }
12
+ ];
@@ -0,0 +1,196 @@
1
+ ---
2
+ import './fire-pattern-origin-analyzer.css';
3
+
4
+ interface Props {
5
+ ui: Record<string, string>;
6
+ }
7
+
8
+ const { ui } = Astro.props;
9
+ ---
10
+
11
+ <section class="fire-origin" data-fire-origin-tool data-has-plan="false">
12
+ <div class="fire-workspace">
13
+ <div class="fire-topbar">
14
+ <label class="fire-command fire-command-load">
15
+ <input id="fire-plan-upload" type="file" accept="image/*" />
16
+ <span>{ui.loadPlan}</span>
17
+ </label>
18
+ <button type="button" class="fire-command" id="fire-reset" disabled>{ui.resetVectors}</button>
19
+ <button type="button" class="fire-command fire-command-export" id="fire-export" disabled>{ui.generateReport}</button>
20
+ </div>
21
+
22
+ <div class="fire-plan-shell">
23
+ <div class="fire-layer-dots" role="group" aria-label={ui.visibleLayers}>
24
+ <button type="button" class="fire-layer-dot" data-fire-layer-toggle="vPattern" data-active="true" aria-label={ui.vPattern} disabled></button>
25
+ <button type="button" class="fire-layer-dot" data-fire-layer-toggle="deepChar" data-active="true" aria-label={ui.deepChar} disabled></button>
26
+ <button type="button" class="fire-layer-dot" data-fire-layer-toggle="sootShadow" data-active="true" aria-label={ui.sootShadow} disabled></button>
27
+ <button type="button" class="fire-layer-dot" data-fire-layer-toggle="cleanBurn" data-active="true" aria-label={ui.cleanBurn} disabled></button>
28
+ </div>
29
+
30
+ <div class="fire-pointer-overlay" id="fire-pointer-overlay">
31
+ <span>{ui.pointerLabel}</span>
32
+ <strong id="fire-pointer-coordinate">--, --</strong>
33
+ </div>
34
+
35
+ <div class="fire-origin-overlay" id="fire-origin-overlay">
36
+ <span>{ui.estimatedOrigin}</span>
37
+ <strong id="fire-origin-coordinate">--, --</strong>
38
+ </div>
39
+
40
+ <button type="button" class="fire-dropzone" id="fire-dropzone">{ui.dropPlan}</button>
41
+
42
+ <div class="fire-radial-menu" id="fire-radial-menu" hidden>
43
+ <button type="button" data-fire-pattern="vPattern">{ui.vPattern}</button>
44
+ <button type="button" data-fire-pattern="deepChar">{ui.deepChar}</button>
45
+ <button type="button" data-fire-pattern="cleanBurn">{ui.cleanBurn}</button>
46
+ <button type="button" data-fire-pattern="sootShadow">{ui.sootShadow}</button>
47
+ </div>
48
+
49
+ <svg id="fire-plan-svg" viewBox="0 0 1000 680" role="img" aria-label={ui.planAria}>
50
+ <defs>
51
+ <pattern id="fire-grid" width="50" height="50" patternUnits="userSpaceOnUse">
52
+ <path d="M 50 0 L 0 0 0 50" fill="none" stroke="currentColor" stroke-width="1" opacity="0.14"></path>
53
+ </pattern>
54
+ </defs>
55
+ <image id="fire-plan-image" x="0" y="0" width="1000" height="680" preserveAspectRatio="xMidYMid slice"></image>
56
+ <rect class="fire-grid-fill" x="0" y="0" width="1000" height="680" fill="url(#fire-grid)"></rect>
57
+ </svg>
58
+ <canvas id="fire-overlay-canvas" width="1000" height="680"></canvas>
59
+ </div>
60
+
61
+ <footer class="fire-statusbar">
62
+ <span>{ui.vectorsLabel}: <strong id="fire-vector-count">0</strong></span>
63
+ <span>{ui.confidenceLabel}: <strong id="fire-confidence-score">0.0%</strong></span>
64
+ <span>{ui.varianceLabel}: <strong id="fire-origin-variance">+-0.0 m</strong></span>
65
+ <span>{ui.modeLabel}: <strong id="fire-mode-label">{ui.awaitingVector}</strong></span>
66
+ </footer>
67
+
68
+ <details class="fire-guide" open>
69
+ <summary>{ui.guideSummary}</summary>
70
+ <div class="fire-guide-body" aria-label={ui.guideTitle}>
71
+ <div class="fire-guide-panels">
72
+ <details open>
73
+ <summary>{ui.flowPanelTitle}</summary>
74
+ <div class="fire-guide-flow">
75
+ <article>
76
+ <strong>{ui.flow1Kicker}</strong>
77
+ <span>{ui.flow1Icon}</span>
78
+ <h3>{ui.flow1Title}</h3>
79
+ <p>{ui.flow1Text}</p>
80
+ </article>
81
+ <article>
82
+ <strong>{ui.flow2Kicker}</strong>
83
+ <span>{ui.flow2Icon}</span>
84
+ <h3>{ui.flow2Title}</h3>
85
+ <p>{ui.flow2Text}</p>
86
+ </article>
87
+ <article>
88
+ <strong>{ui.flow3Kicker}</strong>
89
+ <span>{ui.flow3Icon}</span>
90
+ <h3>{ui.flow3Title}</h3>
91
+ <p>{ui.flow3Text}</p>
92
+ </article>
93
+ <article>
94
+ <strong>{ui.flow4Kicker}</strong>
95
+ <span>{ui.flow4Icon}</span>
96
+ <h3>{ui.flow4Title}</h3>
97
+ <p>{ui.flow4Text}</p>
98
+ </article>
99
+ </div>
100
+ </details>
101
+
102
+ <details open>
103
+ <summary>{ui.legendPanelTitle}</summary>
104
+ <div class="fire-guide-legend" aria-label={ui.indicatorsTitle}>
105
+ <article class="fire-guide-chip fire-guide-chip-v">
106
+ <span></span>
107
+ <strong>{ui.vPattern}</strong>
108
+ <small>{ui.vPatternShort}</small>
109
+ </article>
110
+ <article class="fire-guide-chip fire-guide-chip-char">
111
+ <span></span>
112
+ <strong>{ui.deepChar}</strong>
113
+ <small>{ui.deepCharShort}</small>
114
+ </article>
115
+ <article class="fire-guide-chip fire-guide-chip-soot">
116
+ <span></span>
117
+ <strong>{ui.sootShadow}</strong>
118
+ <small>{ui.sootShadowShort}</small>
119
+ </article>
120
+ <article class="fire-guide-chip fire-guide-chip-clean">
121
+ <span></span>
122
+ <strong>{ui.cleanBurn}</strong>
123
+ <small>{ui.cleanBurnShort}</small>
124
+ </article>
125
+ </div>
126
+ </details>
127
+
128
+ <details open>
129
+ <summary>{ui.readoutPanelTitle}</summary>
130
+ <div class="fire-guide-readouts">
131
+ <article>
132
+ <strong>{ui.vectorsLabel}</strong>
133
+ <p>{ui.resultsPoint1}</p>
134
+ </article>
135
+ <article>
136
+ <strong>{ui.confidenceLabel}</strong>
137
+ <p>{ui.resultsPoint2}</p>
138
+ </article>
139
+ <article>
140
+ <strong>{ui.varianceLabel}</strong>
141
+ <p>{ui.resultsPoint3}</p>
142
+ </article>
143
+ <article>
144
+ <strong>{ui.modeLabel}</strong>
145
+ <p>{ui.resultsPoint4}</p>
146
+ </article>
147
+ </div>
148
+ </details>
149
+
150
+ <details open>
151
+ <summary>{ui.basicsTitle}</summary>
152
+ <div class="fire-guide-panel-copy">
153
+ <p>{ui.basicsIntro}</p>
154
+ </div>
155
+ </details>
156
+
157
+ <details>
158
+ <summary>{ui.indicatorsTitle}</summary>
159
+ <div class="fire-guide-definitions">
160
+ <article>
161
+ <h3>{ui.vPattern}</h3>
162
+ <p>{ui.vPatternExplain}</p>
163
+ </article>
164
+ <article>
165
+ <h3>{ui.deepChar}</h3>
166
+ <p>{ui.deepCharExplain}</p>
167
+ </article>
168
+ <article>
169
+ <h3>{ui.sootShadow}</h3>
170
+ <p>{ui.sootShadowExplain}</p>
171
+ </article>
172
+ <article>
173
+ <h3>{ui.cleanBurn}</h3>
174
+ <p>{ui.cleanBurnExplain}</p>
175
+ </article>
176
+ </div>
177
+ </details>
178
+
179
+ <details>
180
+ <summary>{ui.resultsTitle}</summary>
181
+ <div class="fire-guide-panel-copy">
182
+ <p>{ui.resultsIntro}</p>
183
+ </div>
184
+ </details>
185
+ </div>
186
+ </div>
187
+ </details>
188
+ </div>
189
+ </section>
190
+
191
+ <script id="fire-origin-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
192
+ <script>
193
+ import { initFirePatternOriginAnalyzer } from './view';
194
+
195
+ initFirePatternOriginAnalyzer(JSON.parse(document.getElementById('fire-origin-ui')?.textContent || '{}'));
196
+ </script>
@@ -0,0 +1,32 @@
1
+ import type { ScienceToolEntry, ToolLocaleContent } from '../../types';
2
+
3
+ export interface FirePatternOriginAnalyzerUI {
4
+ [key: string]: string;
5
+ }
6
+
7
+ export type FirePatternOriginAnalyzerLocaleContent = ToolLocaleContent<FirePatternOriginAnalyzerUI>;
8
+
9
+ export const firePatternOriginAnalyzer: ScienceToolEntry<FirePatternOriginAnalyzerUI> = {
10
+ id: 'fire-pattern-origin-analyzer',
11
+ icons: {
12
+ bg: 'mdi:fire-alert',
13
+ fg: 'mdi:vector-polyline',
14
+ },
15
+ i18n: {
16
+ de: () => import('./i18n/de').then((m) => m.content),
17
+ en: () => import('./i18n/en').then((m) => m.content),
18
+ es: () => import('./i18n/es').then((m) => m.content),
19
+ fr: () => import('./i18n/fr').then((m) => m.content),
20
+ id: () => import('./i18n/id').then((m) => m.content),
21
+ it: () => import('./i18n/it').then((m) => m.content),
22
+ ja: () => import('./i18n/ja').then((m) => m.content),
23
+ ko: () => import('./i18n/ko').then((m) => m.content),
24
+ nl: () => import('./i18n/nl').then((m) => m.content),
25
+ pl: () => import('./i18n/pl').then((m) => m.content),
26
+ pt: () => import('./i18n/pt').then((m) => m.content),
27
+ ru: () => import('./i18n/ru').then((m) => m.content),
28
+ sv: () => import('./i18n/sv').then((m) => m.content),
29
+ tr: () => import('./i18n/tr').then((m) => m.content),
30
+ zh: () => import('./i18n/zh').then((m) => m.content),
31
+ },
32
+ };