@jjlmoya/utils-forensic-science 1.13.0 → 1.14.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.
- package/package.json +2 -1
- package/src/category/index.ts +61 -59
- package/src/category/seo.astro +1 -1
- package/src/components/PreviewNavSidebar.astro +1 -1
- package/src/components/PreviewToolbar.astro +1 -1
- package/src/data.ts +1 -1
- package/src/entries.ts +70 -68
- package/src/env.d.ts +1 -1
- package/src/index.ts +32 -31
- package/src/pages/[locale]/[slug].astro +161 -159
- package/src/pages/[locale].astro +8 -5
- package/src/pages/index.astro +1 -1
- package/src/tests/bibliography_wellformed_export.test.ts +46 -0
- package/src/tests/diacritics_density.test.ts +1 -1
- package/src/tests/faq_count.test.ts +19 -19
- package/src/tests/i18n_coverage.test.ts +36 -36
- package/src/tests/inverted_punctuation.test.ts +1 -1
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/mocks/astro_mock.js +1 -1
- package/src/tests/no_h1_in_components.test.ts +1 -1
- package/src/tests/script_density.test.ts +94 -94
- package/src/tests/seo_length.test.ts +46 -46
- package/src/tests/seo_parity.test.ts +2 -7
- package/src/tests/seo_translation_completeness.test.ts +68 -0
- package/src/tests/seo_wellformed_export.test.ts +65 -0
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tests/translation_copy.test.ts +23 -24
- package/src/tool/bloodstain-pattern-origin-analyzer/component.astro +9 -9
- package/src/tool/bloodstain-pattern-origin-analyzer/i18n/zh.ts +1 -1
- package/src/tool/dna-profile-match-probability-lab/bibliography.astro +14 -0
- package/src/tool/dna-profile-match-probability-lab/bibliography.ts +16 -0
- package/src/tool/dna-profile-match-probability-lab/component.astro +121 -0
- package/src/tool/dna-profile-match-probability-lab/controller.ts +159 -0
- package/src/tool/dna-profile-match-probability-lab/dna-profile-match-probability-lab.css +485 -0
- package/src/tool/dna-profile-match-probability-lab/dom-views.ts +93 -0
- package/src/tool/dna-profile-match-probability-lab/entry.ts +29 -0
- package/src/tool/dna-profile-match-probability-lab/evaluator.ts +19 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/de.ts +43 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/en.ts +196 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/es.ts +40 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/fr.ts +10 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/id.ts +41 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/it.ts +10 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/ja.ts +40 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/ko.ts +40 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/nl.ts +29 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/pl.ts +10 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/pt.ts +41 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/ru.ts +29 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/sv.ts +41 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/tr.ts +10 -0
- package/src/tool/dna-profile-match-probability-lab/i18n/zh.ts +29 -0
- package/src/tool/dna-profile-match-probability-lab/index.ts +11 -0
- package/src/tool/dna-profile-match-probability-lab/localize.ts +107 -0
- package/src/tool/dna-profile-match-probability-lab/logic.test.ts +56 -0
- package/src/tool/dna-profile-match-probability-lab/logic.ts +139 -0
- package/src/tool/dna-profile-match-probability-lab/seo.astro +15 -0
- package/src/tool/dna-profile-match-probability-lab/storage.ts +26 -0
- package/src/tool/dna-profile-match-probability-lab/ui.ts +3 -0
- package/src/tool/fire-pattern-origin-analyzer/component.astro +1 -1
- package/src/tool/fire-pattern-origin-analyzer/i18n/zh.ts +5 -1
- package/src/tool/fire-pattern-origin-analyzer/logic.ts +9 -2
- package/src/tool/fire-pattern-origin-analyzer/view-bindings.ts +8 -4
- package/src/tool/fire-pattern-origin-analyzer/view-model.ts +6 -2
- package/src/tool/forensic-age-estimator/bibliography.astro +1 -1
- package/src/tool/forensic-age-estimator/component.astro +1 -1
- package/src/tool/forensic-age-estimator/entry.ts +17 -17
- package/src/tool/forensic-age-estimator/i18n/de.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/en.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/es.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/fr.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/id.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/it.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/nl.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/pl.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/pt.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/ru.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/sv.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/tr.ts +244 -244
- package/src/tool/forensic-age-estimator/i18n/zh.ts +245 -245
- package/src/tool/forensic-age-estimator/index.ts +1 -1
- package/src/tool/forensic-age-estimator/seo.astro +1 -1
- package/src/tool/forensic-blood-test-simulator/component.astro +1 -1
- package/src/tool/forensic-fiber-comparison-microscope/component.astro +1 -1
- package/src/tool/forensic-fiber-comparison-microscope/render.ts +1 -1
- package/src/tool/forensic-fiber-comparison-microscope/view.ts +1 -1
- package/src/tool/forensic-fingerprint-minutiae-identifier/component.astro +2 -2
- package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/ja.ts +2 -1
- package/src/tool/forensic-fingerprint-minutiae-identifier/i18n/zh.ts +2 -0
- package/src/tool/forensic-fingerprint-minutiae-identifier/renderer.ts +9 -8
- package/src/tool/forensic-glass-becke-line-simulator/component.astro +1 -1
- package/src/tool/forensic-glass-becke-line-simulator/view.ts +8 -6
- package/src/tool/forensic-image-authenticity-analyzer/component.astro +1 -1
- package/src/tool/forensic-image-authenticity-analyzer/i18n/de.ts +105 -105
- package/src/tool/forensic-image-authenticity-analyzer/i18n/en.ts +105 -105
- package/src/tool/forensic-image-authenticity-analyzer/i18n/es.ts +105 -105
- package/src/tool/forensic-image-authenticity-analyzer/i18n/fr.ts +105 -105
- package/src/tool/forensic-image-authenticity-analyzer/i18n/id.ts +95 -90
- package/src/tool/forensic-image-authenticity-analyzer/i18n/it.ts +105 -105
- package/src/tool/forensic-image-authenticity-analyzer/i18n/ja.ts +7 -2
- package/src/tool/forensic-image-authenticity-analyzer/i18n/ko.ts +4 -1
- package/src/tool/forensic-image-authenticity-analyzer/i18n/nl.ts +95 -92
- package/src/tool/forensic-image-authenticity-analyzer/i18n/pl.ts +95 -92
- package/src/tool/forensic-image-authenticity-analyzer/i18n/pt.ts +105 -105
- package/src/tool/forensic-image-authenticity-analyzer/i18n/ru.ts +97 -92
- package/src/tool/forensic-image-authenticity-analyzer/i18n/sv.ts +97 -93
- package/src/tool/forensic-image-authenticity-analyzer/i18n/tr.ts +98 -93
- package/src/tool/forensic-image-authenticity-analyzer/i18n/zh.ts +11 -0
- package/src/tool/forensic-microcrystal-drug-simulator/component.astro +1 -1
- package/src/tool/forensic-sex-determinator/component.astro +3 -2
- package/src/tool/forensic-stature-estimator/component.astro +1 -1
- package/src/tool/forensic-stature-estimator/i18n/id.ts +4 -0
- package/src/tool/forensic-stature-estimator/i18n/nl.ts +4 -0
- package/src/tool/forensic-stature-estimator/i18n/ru.ts +4 -0
- package/src/tool/forensic-tlc-ink-simulator/component.astro +1 -1
- package/src/tool/forensic-tlc-ink-simulator/i18n/zh.ts +1 -0
- package/src/tool/forensic-toolmark-striation-matcher/component.astro +1 -1
- package/src/tool/forensic-toolmark-striation-matcher/logic.ts +1 -1
- package/src/tool/forensic-toolmark-striation-matcher/renderer.ts +7 -6
- package/src/tool/forensic-toolmark-striation-matcher/view.ts +19 -20
- package/src/tool/gsr-dispersion-calculator/component.astro +1 -1
- package/src/tool/gsr-dispersion-calculator/logic.ts +1 -1
- package/src/tool/time-of-death-algor-mortis-calculator/entry.ts +2 -0
- package/src/tool/widmark-alcohol-simulator/component.astro +1 -1
- package/src/tool/widmark-alcohol-simulator/i18n/de.ts +5 -0
- package/src/tool/widmark-alcohol-simulator/i18n/fr.ts +2 -1
- package/src/tool/widmark-alcohol-simulator/i18n/id.ts +1 -0
- package/src/tool/widmark-alcohol-simulator/i18n/it.ts +4 -1
- package/src/tool/widmark-alcohol-simulator/i18n/ja.ts +4 -1
- package/src/tool/widmark-alcohol-simulator/i18n/nl.ts +5 -1
- package/src/tool/widmark-alcohol-simulator/i18n/pl.ts +5 -1
- package/src/tool/widmark-alcohol-simulator/i18n/pt.ts +5 -1
- package/src/tool/widmark-alcohol-simulator/i18n/ru.ts +4 -1
- package/src/tool/widmark-alcohol-simulator/i18n/sv.ts +5 -1
- package/src/tool/widmark-alcohol-simulator/i18n/tr.ts +4 -1
- package/src/tool/widmark-alcohol-simulator/i18n/zh.ts +4 -1
- package/src/tools.ts +37 -35
- package/src/types.ts +4 -4
|
@@ -1,95 +1,100 @@
|
|
|
1
|
-
import { bibliography } from '../bibliography';
|
|
2
|
-
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
-
|
|
4
|
-
const slug = 'adli-goruntu-metadata-ve-ozgunluk-analizoru';
|
|
5
|
-
const title = 'Adli Görüntü Metadata ve Özgünlük Analizörü';
|
|
6
|
-
const description = 'Görüntü başlıklarını, EXIF çekim ayrıntılarını, GPS koordinatlarını, düzenleme yazılımı izlerini ve ham baytları tarayıcıda yerel olarak inceleyin.';
|
|
7
|
-
|
|
8
|
-
const howTo = [
|
|
9
|
-
{ name: 'Orijinal delili koruyun', text: 'Adli kopya üzerinden çalışın ve kaynak dosyayı ile kriptografik özetini bu tarayıcı aracının dışında saklayın.' },
|
|
10
|
-
{ name: 'Görüntüyü yerel olarak yükleyin', text: 'Bir JPEG veya PNG sürükleyin ya da seçin. Dosya tarayıcı belleğinde okunur ve yüklenmez.' },
|
|
11
|
-
{ name: 'Metadata ve konumu gözden geçirin', text: 'Çekim zamanı, kamera kimliği, yazılım ve GPS alanlarını olay anlatımı ve edinim kayıtlarıyla karşılaştırın.' },
|
|
12
|
-
{ name: 'Bütünlük sinyallerini yorumlayın', text: 'Düzenleme imzaları ve eksik alanları manipülasyon kanıtı değil, soruşturma ipucu olarak değerlendirin.' },
|
|
13
|
-
{ name: 'Onaltılık önizlemeyi inceleyin', text: 'Vurgulanan başlık ve metadata bölgelerini kullanarak kapsayıcı yapısını tanıyın ve daha derin inceleme için ofsetleri belgeleyin.' },
|
|
14
|
-
];
|
|
15
|
-
|
|
16
|
-
const faq = [
|
|
17
|
-
{ question: 'Metadata bir fotoğrafın özgün olduğunu kanıtlayabilir mi?', answer: 'Hayır. Metadata kaldırılabilir, kopyalanabilir veya değiştirilebilir. Kimlik doğrulama; dosya yapısı, köken, özetler, görsel inceleme, sıkıştırma analizi ve doğrulanmış adli yöntemlerin birlikte kullanılmasını gerektirir.' },
|
|
18
|
-
{ question: 'Adobe veya GIMP imzası kötü niyetli düzenlemeyi kanıtlar mı?', answer: 'Hayır. Yalnızca bir yazılımın metadata yazmış veya dosyayı dışa aktarmış olabileceğini gösterir. Meşru renk düzeltme, editoryal iş akışı veya delil hazırlığı aynı izi bırakabilir.' },
|
|
19
|
-
{ question: 'Görüntü yükleniyor mu?', answer: 'Hayır. Analiz tarayıcı belleğinde yapılır. Yine de hassas materyali herhangi bir yazılımda açmadan önce kuruluşunuzun delil işleme politikasını izleyin.' },
|
|
20
|
-
{ question: 'GPS verileri neden eksik olabilir?', answer: 'Kamera GPS desteklemiyor olabilir, konum kaydı kapalı olabilir, bir platform metadata\'yı kaldırmış olabilir veya dosya yeniden kodlanmış olabilir.' },
|
|
21
|
-
];
|
|
22
|
-
|
|
23
|
-
export const content: ToolLocaleContent = {
|
|
24
|
-
slug,
|
|
25
|
-
title,
|
|
26
|
-
description,
|
|
27
|
-
ui: {
|
|
28
|
-
privacy: 'Yalnızca yerel ikili inceleme',
|
|
29
|
-
dropTitle: 'Görüntüyü delil masasına yerleştirin',
|
|
30
|
-
dropHint: 'Buraya bir JPEG veya PNG bırakın ya da dosya seçin. Hiçbir şey yüklenmez.',
|
|
31
|
-
chooseFile: 'Görüntü seç',
|
|
32
|
-
replaceFile: 'Görüntüyü değiştir',
|
|
33
|
-
waiting: 'Delil bekleniyor',
|
|
34
|
-
metadata: 'Çekim metadata\'sı',
|
|
35
|
-
integrity: 'Bütünlük sinyalleri',
|
|
36
|
-
location: 'Kaydedilen konum',
|
|
37
|
-
hex: 'Onaltılık delil penceresi',
|
|
38
|
-
hexHint: 'İlk 512 bayt · camgöbeği başlık · kehribar metadata · nötr görüntü verisi',
|
|
39
|
-
noData: 'Okunabilir değer yok',
|
|
40
|
-
noGps: 'Okunabilir GPS koordinatı bulunamadı.',
|
|
41
|
-
mapLink: 'Koordinatları OpenStreetMap\'te aç',
|
|
42
|
-
score: 'Sezgisel güven',
|
|
43
|
-
disclaimer: 'Yüksek puan özgünlüğü kanıtlamaz. Orijinali koruyun, kriptografik özetler hesaplayın ve vaka sonuçları için doğrulanmış laboratuvar iş akışları kullanın.',
|
|
44
|
-
fileName: 'Dosya',
|
|
45
|
-
fileSize: 'Boyut',
|
|
46
|
-
fileType: 'Kapsayıcı',
|
|
47
|
-
camera: 'Kamera',
|
|
48
|
-
captured: 'Çekildi',
|
|
49
|
-
software: 'Yazılım',
|
|
50
|
-
coordinates: 'Koordinatlar',
|
|
51
|
-
statusNoObvious: 'Belirgin düzenleme göstergesi yok',
|
|
52
|
-
statusReview: 'İnceleme önerilir',
|
|
53
|
-
statusEditing: 'Düzenleme imzası tespit edildi',
|
|
54
|
-
processing: 'İkili delil okunuyor...',
|
|
55
|
-
loadError: 'Dosya analiz edilemedi. Geçerli bir JPEG veya PNG görüntüsü seçin.',
|
|
56
|
-
},
|
|
57
|
-
seo: [
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
|
|
4
|
+
const slug = 'adli-goruntu-metadata-ve-ozgunluk-analizoru';
|
|
5
|
+
const title = 'Adli Görüntü Metadata ve Özgünlük Analizörü';
|
|
6
|
+
const description = 'Görüntü başlıklarını, EXIF çekim ayrıntılarını, GPS koordinatlarını, düzenleme yazılımı izlerini ve ham baytları tarayıcıda yerel olarak inceleyin.';
|
|
7
|
+
|
|
8
|
+
const howTo = [
|
|
9
|
+
{ name: 'Orijinal delili koruyun', text: 'Adli kopya üzerinden çalışın ve kaynak dosyayı ile kriptografik özetini bu tarayıcı aracının dışında saklayın.' },
|
|
10
|
+
{ name: 'Görüntüyü yerel olarak yükleyin', text: 'Bir JPEG veya PNG sürükleyin ya da seçin. Dosya tarayıcı belleğinde okunur ve yüklenmez.' },
|
|
11
|
+
{ name: 'Metadata ve konumu gözden geçirin', text: 'Çekim zamanı, kamera kimliği, yazılım ve GPS alanlarını olay anlatımı ve edinim kayıtlarıyla karşılaştırın.' },
|
|
12
|
+
{ name: 'Bütünlük sinyallerini yorumlayın', text: 'Düzenleme imzaları ve eksik alanları manipülasyon kanıtı değil, soruşturma ipucu olarak değerlendirin.' },
|
|
13
|
+
{ name: 'Onaltılık önizlemeyi inceleyin', text: 'Vurgulanan başlık ve metadata bölgelerini kullanarak kapsayıcı yapısını tanıyın ve daha derin inceleme için ofsetleri belgeleyin.' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
const faq = [
|
|
17
|
+
{ question: 'Metadata bir fotoğrafın özgün olduğunu kanıtlayabilir mi?', answer: 'Hayır. Metadata kaldırılabilir, kopyalanabilir veya değiştirilebilir. Kimlik doğrulama; dosya yapısı, köken, özetler, görsel inceleme, sıkıştırma analizi ve doğrulanmış adli yöntemlerin birlikte kullanılmasını gerektirir.' },
|
|
18
|
+
{ question: 'Adobe veya GIMP imzası kötü niyetli düzenlemeyi kanıtlar mı?', answer: 'Hayır. Yalnızca bir yazılımın metadata yazmış veya dosyayı dışa aktarmış olabileceğini gösterir. Meşru renk düzeltme, editoryal iş akışı veya delil hazırlığı aynı izi bırakabilir.' },
|
|
19
|
+
{ question: 'Görüntü yükleniyor mu?', answer: 'Hayır. Analiz tarayıcı belleğinde yapılır. Yine de hassas materyali herhangi bir yazılımda açmadan önce kuruluşunuzun delil işleme politikasını izleyin.' },
|
|
20
|
+
{ question: 'GPS verileri neden eksik olabilir?', answer: 'Kamera GPS desteklemiyor olabilir, konum kaydı kapalı olabilir, bir platform metadata\'yı kaldırmış olabilir veya dosya yeniden kodlanmış olabilir.' },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export const content: ToolLocaleContent = {
|
|
24
|
+
slug,
|
|
25
|
+
title,
|
|
26
|
+
description,
|
|
27
|
+
ui: {
|
|
28
|
+
privacy: 'Yalnızca yerel ikili inceleme',
|
|
29
|
+
dropTitle: 'Görüntüyü delil masasına yerleştirin',
|
|
30
|
+
dropHint: 'Buraya bir JPEG veya PNG bırakın ya da dosya seçin. Hiçbir şey yüklenmez.',
|
|
31
|
+
chooseFile: 'Görüntü seç',
|
|
32
|
+
replaceFile: 'Görüntüyü değiştir',
|
|
33
|
+
waiting: 'Delil bekleniyor',
|
|
34
|
+
metadata: 'Çekim metadata\'sı',
|
|
35
|
+
integrity: 'Bütünlük sinyalleri',
|
|
36
|
+
location: 'Kaydedilen konum',
|
|
37
|
+
hex: 'Onaltılık delil penceresi',
|
|
38
|
+
hexHint: 'İlk 512 bayt · camgöbeği başlık · kehribar metadata · nötr görüntü verisi',
|
|
39
|
+
noData: 'Okunabilir değer yok',
|
|
40
|
+
noGps: 'Okunabilir GPS koordinatı bulunamadı.',
|
|
41
|
+
mapLink: 'Koordinatları OpenStreetMap\'te aç',
|
|
42
|
+
score: 'Sezgisel güven',
|
|
43
|
+
disclaimer: 'Yüksek puan özgünlüğü kanıtlamaz. Orijinali koruyun, kriptografik özetler hesaplayın ve vaka sonuçları için doğrulanmış laboratuvar iş akışları kullanın.',
|
|
44
|
+
fileName: 'Dosya',
|
|
45
|
+
fileSize: 'Boyut',
|
|
46
|
+
fileType: 'Kapsayıcı',
|
|
47
|
+
camera: 'Kamera',
|
|
48
|
+
captured: 'Çekildi',
|
|
49
|
+
software: 'Yazılım',
|
|
50
|
+
coordinates: 'Koordinatlar',
|
|
51
|
+
statusNoObvious: 'Belirgin düzenleme göstergesi yok',
|
|
52
|
+
statusReview: 'İnceleme önerilir',
|
|
53
|
+
statusEditing: 'Düzenleme imzası tespit edildi',
|
|
54
|
+
processing: 'İkili delil okunuyor...',
|
|
55
|
+
loadError: 'Dosya analiz edilemedi. Geçerli bir JPEG veya PNG görüntüsü seçin.',
|
|
56
|
+
},
|
|
57
|
+
seo: [
|
|
58
58
|
{ type: 'title', text: 'Görüntü metadata\'sı ve özgünlük göstergeleri nasıl analiz edilir', level: 2 },
|
|
59
|
-
{ type: 'paragraph', html:
|
|
60
|
-
{ type: 'paragraph', html:
|
|
61
|
-
{ type: 'paragraph', html:
|
|
62
|
-
{ type: '
|
|
63
|
-
{ type: 'paragraph', html:
|
|
64
|
-
{ type: '
|
|
65
|
-
{ type: 'paragraph', html: '
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
{ type: 'paragraph', html: "
|
|
73
|
-
{ type: 'paragraph', html: "
|
|
74
|
-
{ type: 'paragraph', html: "
|
|
75
|
-
{ type: 'paragraph', html: "
|
|
76
|
-
{ type: 'paragraph', html: "
|
|
77
|
-
{ type: 'paragraph', html: "
|
|
78
|
-
{ type: 'paragraph', html: "
|
|
79
|
-
{ type: 'paragraph', html: "
|
|
80
|
-
{ type: 'paragraph', html: "
|
|
81
|
-
{ type: 'paragraph', html: "
|
|
82
|
-
{ type: 'paragraph', html: "
|
|
83
|
-
{ type: 'paragraph', html: "
|
|
84
|
-
{ type: 'paragraph', html: "
|
|
85
|
-
{ type: 'paragraph', html: "
|
|
59
|
+
{ type: 'paragraph', html: "Çalışma varsayımını destekleyen, ona karşı çıkan ve henüz eksik olan bulguları ayrı ayrı kaydedin. Bu ayrım teknik ipucu ile nihai uzman görüşü arasındaki sınırı korur." },
|
|
60
|
+
{ type: 'paragraph', html: "Sonuç, dosyanın kökenini ve korunma durumunu kontrol etmek için başlangıç noktasıdır. Gözlenen işaretleri, bulunmayan işaretleri ve ihtiyaç duyulan ek bilgileri ayrı ayrı açıklayın. Bu kayıt, buluşsal puanın özgünlük hakkında kesin hüküm gibi yanlış anlaşılmasını önler." },
|
|
61
|
+
{ type: 'paragraph', html: "Dosya uzantısı veya tek bir etiket biçimi, düzenleme geçmişini ya da özgünlüğü kanıtlayamaz. Gerçek başlık yapısını, piksel boyutunu, renk profilini, küçük önizlemeyi ve yazılım bilgilerini kontrol ederek edinim kaydıyla karşılaştırın. Özet değeri dosyanın aynı olduğunu doğrular, ancak fotoğraftaki içeriğin gerçekliğini kanıtlamaz. Paylaşım platformlarının yeniden sıkıştırmasını ve meta veri silmesini hesaba katın; incelemenin kapsamını ve kalan belirsizliği kaydedin. Hipotezi destekleyen, ona karşı çıkan ve henüz elde olmayan bulguları ayrı ayrı açıklayın." },
|
|
62
|
+
{ type: 'paragraph', html: "Çekim zamanı veya GPS bilgisinin bulunmaması görüntünün değiştirildiğini otomatik olarak göstermez. Kamera ayarları, paylaşım platformları, gizlilik seçenekleri ve yeniden kaydetme işlemleri etiketleri silebilir ya da yeniden yazabilir. Bu nedenle dosya başlığını, piksel boyutunu, renk profilini, küçük önizlemeyi, yazılım etiketlerini ve edinim kaydını birlikte karşılaştırın. Özgün dosyayı kontrollü ortamda saklayın, analizden önce özetini alın ve kopyaları, dönüşümleri, analiz ortamını kaydedin. Sonucu ek inceleme için ipucu sayın; köken, tanık bilgileri, cihaz kayıtları ve doğrulanmış yöntemlerle birlikte değerlendirin." },
|
|
63
|
+
{ type: 'paragraph', html: "Kayıtta edinim tarihini, depolama ortamını, özeti, analiz ortamını, incelenen alanları, gözlemleri ve açık soruları ayrı ayrı belirtin. Yalnızca eksik meta veriye bakarak düzenleme sonucu çıkarmayın. Bulguları dosyanın kökeni, edinim günlüğü ve saklama durumu ile karşılaştırın; böylece başka bir incelemeci aynı dosyayı yeniden kontrol edebilir. Kopya ve dönüştürme adımlarını da kaydedin ve buluşsal işareti nihai uzman görüşünden ayırın." },
|
|
64
|
+
{ type: 'paragraph', html: 'Adli görüntü metadata analizörü; araştırmacıların, gazetecilerin, hukuk ekiplerinin, uyum denetçilerinin ve araştırmacıların <strong>görüntü metadata\'sı bir fotoğraf hakkında gerçekten ne söyleyebilir?</strong> sorusuna cevap bulmasına yardımcı olur. Metadata, çekim, konum, yazılım işlemesi ve dosya yapısı hakkında yararlı ipuçları sunabilir; ancak tek başına bir doğruluk makinesi değildir. En büyük değeri ön elemede ortaya çıkar.' },
|
|
65
|
+
{ type: 'paragraph', html: 'Bu tarayıcı aracı, ham EXIF dökümünden daha fazlasını isteyen kullanıcılar için tasarlanmıştır. Seçilen JPEG veya PNG\'yi yerel olarak okur ve kamera alanlarını, çekim zaman damgalarını, yazılım etiketlerini, koordinatları, kapsayıcı ipuçlarını ve dosyanın ilk baytlarını tek yerde gösterir. Bu da <em>fotoğraf özgünlük kontrolü</em>, <em>EXIF metadata analizi</em> ve <em>bir görüntünün düzenlenip düzenlenmediği nasıl anlaşılır</em> gibi arama niyetlerine karşılık gelir.' },
|
|
66
|
+
{ type: 'paragraph', html: 'En önemli ilke, sonucun hüküm olarak değil bağlam olarak okunması gerektiğidir. Bir dosya yararlı metadata içerebilir ve yine de yanıltıcı olabilir. Bu nedenle metadata; köken, özetler, tanık anlatımları ve doğrulanmış inceleme yöntemleriyle karşılaştırılması gereken bir kanıt katmanı olarak ele alınmalıdır.' },
|
|
67
|
+
{ type: 'title', text: 'EXIF\'in Söyleyebilecekleri ve Söyleyemeyecekleri', level: 3 },
|
|
68
|
+
{ type: 'paragraph', html: 'EXIF (Exchangeable Image File Format) metadata\'sı bir fotoğraf makinesinin çekim anında dosyaya kaydettiği teknik bilgiler bütünüdür. Kamera modeli ve üreticisi, çekim tarihi ve saati, enstantane hızı, diyafram açıklığı, ISO değeri, odak uzaklığı, flaş kullanımı, beyaz dengesi ve çözünürlük gibi parametreleri içerir. Bu alanlar bir fotoğrafın hangi koşullar altında çekildiğine dair değerli ipuçları sağlar. Ancak EXIF metadata\'sının sınırlamalarını anlamak da en az içerdiği bilgiler kadar önemlidir. EXIF alanları standart metadata düzenleme araçlarıyla kolayca değiştirilebilir, kopyalanabilir veya tamamen silinebilir. Bir fotoğrafın EXIF verilerinin bozulmamış olması, o fotoğrafın orijinal olduğu anlamına gelmez. Bu nedenle EXIF analizi, her zaman diğer adli yöntemlerle ve bağımsız kanıtlarla desteklenmesi gereken bir başlangıç noktasıdır.' },
|
|
69
|
+
{ type: 'title', text: 'GPS Metadata\'yı Sorumlu Bir Şekilde Okuma', level: 3 },
|
|
70
|
+
{ type: 'paragraph', html: 'GPS metadata\'sı bir görüntünün çekildiği coğrafi konumu enlem ve boylam koordinatları olarak kaydeder. Bazı kameralar ve akıllı telefonlar ayrıca yükseklik, yön ve GPS hassasiyet bilgilerini de ekler. Bu veriler bir fotoğrafın nerede çekildiğini harita üzerinde doğrulamak için kritik öneme sahiptir. GPS metadata\'sını sorumlu bir şekilde okumak, bu verileri mutlak gerçek olarak değil, doğrulanması gereken bir ipucu olarak ele almayı gerektirir. Koordinatlar yanlış olabilir, kasıtlı olarak değiştirilmiş olabilir veya GPS sinyali alınamayan bir ortamda çekim yapıldığı için hatalı kaydedilmiş olabilir. Ayrıca, mahremiyet ve güvenlik açısından, GPS metadata\'sı hassas konum bilgilerini ifşa edebileceğinden, delil paylaşımı öncesinde bu alanların temizlenmesi veya maskelenmesi değerlendirilmelidir.' },
|
|
71
|
+
|
|
72
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },
|
|
73
|
+
{ type: 'paragraph', html: "Kullanmadan önce sonucu hesaplayıcının gösterdiği varsayımlarla birlikte yorumlayın." },
|
|
74
|
+
{ type: 'paragraph', html: "Girdileri, birimleri, yuvarlamayı, tarihi ve yargı alanını kontrol edin; her biri tahmini değiştirebilir." },
|
|
75
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },
|
|
76
|
+
{ type: 'paragraph', html: "Kullanmadan önce sonucu hesaplayıcının gösterdiği varsayımlarla birlikte yorumlayın." },
|
|
77
|
+
{ type: 'paragraph', html: "Girdileri, birimleri, yuvarlamayı, tarihi ve yargı alanını kontrol edin; her biri tahmini değiştirebilir." },
|
|
78
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },
|
|
79
|
+
{ type: 'paragraph', html: "Kullanmadan önce sonucu hesaplayıcının gösterdiği varsayımlarla birlikte yorumlayın." },
|
|
80
|
+
{ type: 'paragraph', html: "Girdileri, birimleri, yuvarlamayı, tarihi ve yargı alanını kontrol edin; her biri tahmini değiştirebilir." },
|
|
81
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },
|
|
82
|
+
{ type: 'paragraph', html: "Kullanmadan önce sonucu hesaplayıcının gösterdiği varsayımlarla birlikte yorumlayın." },
|
|
83
|
+
{ type: 'paragraph', html: "Girdileri, birimleri, yuvarlamayı, tarihi ve yargı alanını kontrol edin; her biri tahmini değiştirebilir." },
|
|
84
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },
|
|
85
|
+
{ type: 'paragraph', html: "Kullanmadan önce sonucu hesaplayıcının gösterdiği varsayımlarla birlikte yorumlayın." },
|
|
86
|
+
{ type: 'paragraph', html: "Girdileri, birimleri, yuvarlamayı, tarihi ve yargı alanını kontrol edin; her biri tahmini değiştirebilir." },
|
|
87
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },
|
|
88
|
+
{ type: 'paragraph', html: "Kullanmadan önce sonucu hesaplayıcının gösterdiği varsayımlarla birlikte yorumlayın." },
|
|
89
|
+
{ type: 'paragraph', html: "Girdileri, birimleri, yuvarlamayı, tarihi ve yargı alanını kontrol edin; her biri tahmini değiştirebilir." },
|
|
90
|
+
{ type: 'paragraph', html: "Sonucu planlama ve senaryo karşılaştırması için kullanın; resmî hesabın veya uzman görüşünün yerine geçmez." },],
|
|
86
91
|
faq,
|
|
87
|
-
bibliography,
|
|
88
|
-
howTo,
|
|
89
|
-
schemas: [
|
|
90
|
-
{ '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'ForensicApplication', operatingSystem: 'Any' },
|
|
91
|
-
{ '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) },
|
|
92
|
-
{ '@context': 'https://schema.org', '@type': 'HowTo', name: title, step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) },
|
|
93
|
-
],
|
|
94
|
-
};
|
|
95
|
-
|
|
92
|
+
bibliography,
|
|
93
|
+
howTo,
|
|
94
|
+
schemas: [
|
|
95
|
+
{ '@context': 'https://schema.org', '@type': 'SoftwareApplication', name: title, description, applicationCategory: 'ForensicApplication', operatingSystem: 'Any' },
|
|
96
|
+
{ '@context': 'https://schema.org', '@type': 'FAQPage', mainEntity: faq.map((item) => ({ '@type': 'Question', name: item.question, acceptedAnswer: { '@type': 'Answer', text: item.answer } })) },
|
|
97
|
+
{ '@context': 'https://schema.org', '@type': 'HowTo', name: title, step: howTo.map((step) => ({ '@type': 'HowToStep', name: step.name, text: step.text })) },
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
|
|
@@ -56,6 +56,17 @@ export const content: ToolLocaleContent = {
|
|
|
56
56
|
},
|
|
57
57
|
seo: [
|
|
58
58
|
{ type: 'title', text: '如何分析图像元数据和真实性信号', level: 2 },
|
|
59
|
+
{ type: 'paragraph', html: '所有观察都应放回具体的证据处理流程中理解,并保留复核所需的上下文。' },
|
|
60
|
+
{ type: 'paragraph', html: '如需向他人说明结果,请同时提供输入文件的哈希、检查日期、使用的浏览器环境和关键观察项。没有这些上下文时,单个分数很容易被过度解释,也不利于复核。' },
|
|
61
|
+
{ type: 'paragraph', html: '任何结论都应说明证据的来源、处理步骤和适用限制。清晰记录这些信息有助于后续复核,也能避免把工具的筛查提示误写成已经完成的真实性鉴定。' },
|
|
62
|
+
{ type: 'paragraph', html: '如果图像要进入正式调查流程,请保留原始文件和工作副本的关系,并为每次处理记录操作者、时间、软件和输出文件。不要用浏览器中的显示结果覆盖原始证据,也不要把缺少元数据解释为恶意行为。将异常作为待验证的问题,与独立来源进行交叉检查,并在报告中说明本工具不能完成的检测。' },
|
|
63
|
+
{ type: 'paragraph', html: '分析时还应注意文件的生成路径和保存方式。原始相机文件、邮件附件、聊天软件导出的副本和网页截图可能具有完全不同的结构,不能把它们当作同一层级的材料比较。请先确定正在检查的文件是否为原始采集物,再把技术发现与事件时间线、设备记录、图像内容和其他证据相互印证。报告中应保留原始哈希、软件版本、输入文件、检查时间和限制条件,使结论能够被复核。' },
|
|
64
|
+
{ type: 'paragraph', html: '请分别记录支持当前假设、与假设冲突以及尚未获得的证据。这样可以清楚区分技术线索和最终意见。对于从社交平台下载、截图或重新导出的图像,必须明确标记其来源链条,因为平台处理可能改变压缩方式、尺寸、颜色配置和元数据。原始文件应当在受控介质中保存,并在分析前计算哈希。检查人员还应记录使用的工具版本、分析时间、观察结果和未解决的问题。缺失字段可能来自隐私设置或正常导出流程,不能独立证明篡改;相反,存在编辑软件标签也不能证明内容被恶意改变。应把多种独立证据放在同一时间线中比较,并在报告中清楚说明哪些结论只是筛查结果、哪些结论需要实验室验证。' },
|
|
65
|
+
{ type: 'paragraph', html: '检查结果是核对文件来源和保存状态的起点。请分别说明观察到的信号、没有观察到的信号以及仍需获取的资料。这样可以避免把启发式评分误解为关于图像真实性的最终结论。' },
|
|
66
|
+
{ type: 'paragraph', html: '如果文件来自社交平台、截图或重新导出的副本,应明确标注其来源链条。相同图像在不同软件中保存后可能产生不同的元数据;因此应保留原始文件、计算哈希并记录转换过程。对敏感材料进行分析时,优先使用受控的离线环境,并按照机构的证据处理规则保存记录。' },
|
|
67
|
+
{ type: 'paragraph', html: '文件扩展名或单个标签不能证明格式、编辑历史或真实性。请检查实际文件头、像素尺寸、色彩配置、缩略图和软件信息,并与采集记录对照。哈希可以确认文件是否相同,却不能证明照片内容真实。还要考虑分享平台重新压缩或删除元数据的影响,并记录检查范围和剩余的不确定性。分别说明哪些发现支持当前假设、哪些发现与假设冲突,以及还需要哪些资料。' },
|
|
68
|
+
{ type: 'paragraph', html: '拍摄时间或GPS缺失并不自动表示图像被篡改。相机设置、分享平台、隐私选项和重新保存都可能删除或重写标签。因此应同时比较文件头、像素尺寸、色彩配置、缩略图、软件标签和采集记录。请保存受控的原始副本,在分析前计算哈希,并记录复制、转换和分析环境。结果只能作为进一步检查的线索,还要结合文件来源、证词、设备记录和经过验证的方法判断。' },
|
|
69
|
+
{ type: 'paragraph', html: '记录获取时间、保存介质、哈希值、分析环境、检查项目、观察结果和未解决问题。不要仅凭缺失的元数据认定图像被编辑,应把结果与文件来源、采集日志和保存状态对照。记录每次复制或转换,让其他检查人员可以复核同一文件,并区分启发式线索与最终专家意见。' },
|
|
59
70
|
{ type: 'paragraph', html: '图像元数据法证分析器可以帮助调查人员、记者、法务团队、合规审查人员和研究者回答一个高意图问题:<strong>图像元数据究竟能告诉我们什么?</strong> 元数据能够提供关于拍摄、地点、软件处理和文件结构的线索,但它并不是独立的真相机器。它最大的价值在于分流和筛查,帮助你判断哪些文件值得进一步深入检查。' },
|
|
60
71
|
{ type: 'paragraph', html: '这个浏览器工具面向那些不满足于原始 EXIF 转储的用户。它会在本地读取所选 JPEG 或 PNG,并集中呈现相机字段、拍摄时间、软件标签、坐标、容器线索以及文件开头字节。这回应了诸如 <em>照片真实性检查</em>、<em>EXIF 元数据分析</em>、<em>如何判断图片是否被编辑</em> 等常见搜索意图。' },
|
|
61
72
|
{ type: 'paragraph', html: '最重要的原则是:结果应该被视为语境,而不是裁决。一个文件可能拥有有用的元数据却依然具有误导性;也可能元数据很少但依然真实。因此,元数据必须作为证据层之一,与来源、哈希、证言、设备历史和经过验证的检验方法进行交叉比对。' },
|
|
@@ -85,7 +85,7 @@ const { ui } = Astro.props;
|
|
|
85
85
|
</div>
|
|
86
86
|
</section>
|
|
87
87
|
|
|
88
|
-
<script id="microcrystal-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
88
|
+
<script is:inline id="microcrystal-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
89
89
|
<script>
|
|
90
90
|
import { CrystallographyEngine } from './logic';
|
|
91
91
|
import type { CrystalHabit, CrystalReagent, CrystalSeed, DrugSample } from './logic';
|
|
@@ -208,7 +208,7 @@ const regions = [
|
|
|
208
208
|
</div>
|
|
209
209
|
</div>
|
|
210
210
|
|
|
211
|
-
<script id="sex-ui-data" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
211
|
+
<script is:inline id="sex-ui-data" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
212
212
|
|
|
213
213
|
<script>
|
|
214
214
|
import { determineSex } from './logic';
|
|
@@ -392,7 +392,8 @@ const regions = [
|
|
|
392
392
|
function applyStatusText(field: string, val: number) {
|
|
393
393
|
const statusEl = document.getElementById(`status-${field}`);
|
|
394
394
|
if (!statusEl) return;
|
|
395
|
-
|
|
395
|
+
const scoreLabel = scoreLabels[val];
|
|
396
|
+
statusEl.textContent = scoreLabel ? ui[scoreLabel] ?? '' : '';
|
|
396
397
|
}
|
|
397
398
|
|
|
398
399
|
function applySvgState(field: string, val: number) {
|
|
@@ -42,7 +42,7 @@ const { ui } = content;
|
|
|
42
42
|
</div>
|
|
43
43
|
</div>
|
|
44
44
|
|
|
45
|
-
<script id="stature-ui-data" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
45
|
+
<script is:inline id="stature-ui-data" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
46
46
|
|
|
47
47
|
<script>
|
|
48
48
|
import './script';
|
|
@@ -156,6 +156,10 @@ export const content: ToolLocaleContent = {
|
|
|
156
156
|
{
|
|
157
157
|
type: 'paragraph',
|
|
158
158
|
html: 'Sampel referensi Trotter-Gleser lahir pada akhir abad ke-19 dan awal abad ke-20. Karena peningkatan gizi, populasi modern mengalami peningkatan tinggi rata-rata (tren sekuler). Antropolog modern saat ini sering melengkapi analisis menggunakan database baru seperti FORDISC.'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'paragraph',
|
|
162
|
+
html: 'Gunakan estimasi ini sebagai rentang awal untuk rekonstruksi biologis. Catat tulang mana yang diukur, apakah epifisis atau maleolus termasuk, sisi tubuh, kondisi fragmentasi, populasi rujukan, dan galat standar yang dipakai. Perbedaan kecil dalam definisi pengukuran dapat mengubah hasil beberapa sentimeter, sehingga estimasi tinggi badan harus dibaca bersama pemeriksaan antropologis dan konteks identifikasi lainnya.'
|
|
159
163
|
}
|
|
160
164
|
],
|
|
161
165
|
faq,
|
|
@@ -156,6 +156,10 @@ export const content: ToolLocaleContent = {
|
|
|
156
156
|
{
|
|
157
157
|
type: 'paragraph',
|
|
158
158
|
html: 'De referentiedata stammen van individuen geboren rond 1900. Door verbeterde voeding zijn moderne populaties gemiddeld langer geworden (seculaire trend). Hedendaagse forensisch onderzoekers vullen Trotter-Gleser daarom vaak aan met database-software zoals FORDISC.'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'paragraph',
|
|
162
|
+
html: 'Gebruik de uitkomst als een eerste bereik voor biologische reconstructie. Noteer welk bot is gemeten, welke meetdefinitie is gebruikt, de referentiepopulatie en de standaardfout. Een verschil in meetprotocol kan de schatting met meerdere centimeters veranderen; combineer de uitkomst daarom altijd met antropologische beoordeling en andere identificatiegegevens.'
|
|
159
163
|
}
|
|
160
164
|
],
|
|
161
165
|
faq,
|
|
@@ -156,6 +156,10 @@ export const content: ToolLocaleContent = {
|
|
|
156
156
|
{
|
|
157
157
|
type: 'paragraph',
|
|
158
158
|
html: 'Исходные выборки Троттер-Глезер отражают условия жизни конца XIX - начала XX века. Современные поколения стали выше (акселерация). В современной практике формулы Троттер-Глезер часто дополняют новыми базами данных, такими как FORDISC.'
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
type: 'paragraph',
|
|
162
|
+
html: 'Используйте оценку как исходный диапазон для биологической реконструкции. Зафиксируйте, какая кость измерена, входила ли лодыжка в измерение, какая референсная популяция и стандартная ошибка применены. Различия в протоколе могут изменить результат на несколько сантиметров, поэтому оценку следует сопоставлять с антропологическими признаками и другими данными идентификации. Отдельно отмечайте состояние фрагмента, сторону тела и округление. Модель показывает вероятный диапазон, а не точный рост конкретного человека; итоговое заключение требует проверки специалистом. Такой журнал исходных данных делает расчёт прозрачным для повторной проверки и помогает не выдавать статистическую оценку за индивидуальное измерение.'
|
|
159
163
|
}
|
|
160
164
|
],
|
|
161
165
|
faq,
|
|
@@ -92,7 +92,7 @@ const rulerMarks = (ui.rulerMarks ?? '').split(',');
|
|
|
92
92
|
</div>
|
|
93
93
|
</section>
|
|
94
94
|
|
|
95
|
-
<script id="tlc-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
95
|
+
<script is:inline id="tlc-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
96
96
|
<script>
|
|
97
97
|
import { ChromatographyPhysics } from './logic';
|
|
98
98
|
import type { InkSample, SolventSystem, TlcBand } from './logic';
|
|
@@ -196,6 +196,7 @@ export const content: ToolLocaleContent = {
|
|
|
196
196
|
title: '切勿夸大墨水色谱分析的论证作用',
|
|
197
197
|
html: '浏览器模拟无法检查纸张、墨水年龄、提取化学过程、薄层板质量、污染或进行仪器确证。使用它来学习测量逻辑和解释限制,而在处理实际案件证据时,请完全依赖经过验证的专业法医文书检验鉴定方法。',
|
|
198
198
|
},
|
|
199
|
+
{ type: 'paragraph', html: '比较时应同时记录样本来源、提取位置、溶剂体系、展开距离和观察条件。只有在相同实验条件下取得的色谱结果才适合直接比较;任何差异都需要结合文件背景和其他独立证据解释。' },
|
|
199
200
|
|
|
200
201
|
{ type: 'paragraph', html: "使用前请结合计算器显示的假设一起解读结果。" },
|
|
201
202
|
{ type: 'paragraph', html: "请检查输入值、单位、四舍五入方式、日期和司法辖区,因为每项都可能改变估算。" },],
|
|
@@ -113,7 +113,7 @@ const { ui } = Astro.props;
|
|
|
113
113
|
</div>
|
|
114
114
|
</section>
|
|
115
115
|
|
|
116
|
-
<script id="toolmark-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
116
|
+
<script is:inline id="toolmark-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
117
117
|
<script>
|
|
118
118
|
import { initToolmarkStriationMatcher } from './view';
|
|
119
119
|
|
|
@@ -42,7 +42,7 @@ export class StriationMatcher {
|
|
|
42
42
|
const seed = PROFILE_SEEDS[profile] ?? PROFILE_SEEDS.screwdriver;
|
|
43
43
|
const relief: number[] = [];
|
|
44
44
|
for (let i = 0; i < 48; i += 1) {
|
|
45
|
-
const base = seed[i % seed.length];
|
|
45
|
+
const base = seed[i % seed.length] ?? 0;
|
|
46
46
|
const wave = Math.sin((i * 0.72) + (offsetMicrons / 18)) * 0.18;
|
|
47
47
|
const tilt = Math.sin((rotationDegrees * Math.PI / 180) + (i * 0.17)) * 0.08;
|
|
48
48
|
relief.push(Number(clamp(base + wave + tilt, 0.04, 1).toFixed(3)));
|
|
@@ -57,7 +57,7 @@ function panelColor(known: boolean, dark: boolean, end = false): string {
|
|
|
57
57
|
const subject = known ? 'known' : 'questioned';
|
|
58
58
|
const theme = dark ? 'Dark' : 'Light';
|
|
59
59
|
const side = end ? 'End' : 'Start';
|
|
60
|
-
return PANEL_COLORS[`${subject}${theme}${side}`];
|
|
60
|
+
return PANEL_COLORS[`${subject}${theme}${side}`] ?? '#17252d';
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function roundRect(ctx: CanvasRenderingContext2D, rect: Rect): void {
|
|
@@ -130,14 +130,15 @@ function drawDemoStriations(ctx: CanvasRenderingContext2D, config: PanelConfig):
|
|
|
130
130
|
function drawDemoLine(ctx: CanvasRenderingContext2D, config: DemoLineConfig): void {
|
|
131
131
|
const seed = config.result.relief[(config.index + 48) % config.result.relief.length];
|
|
132
132
|
const px = (config.index * 18) + config.lateral;
|
|
133
|
-
const
|
|
133
|
+
const reliefSeed = seed ?? 0;
|
|
134
|
+
const depth = 72 + reliefSeed * 132;
|
|
134
135
|
ctx.shadowColor = config.dark ? 'rgba(20,184,166,0.2)' : 'rgba(20,184,166,0.14)';
|
|
135
|
-
ctx.shadowBlur =
|
|
136
|
-
ctx.strokeStyle = config.dark ? `rgba(226,232,240,${0.22 +
|
|
137
|
-
ctx.lineWidth = 1.8 +
|
|
136
|
+
ctx.shadowBlur = reliefSeed > 0.72 ? 10 : 0;
|
|
137
|
+
ctx.strokeStyle = config.dark ? `rgba(226,232,240,${0.22 + reliefSeed * 0.52})` : `rgba(31,43,50,${0.24 + reliefSeed * 0.52})`;
|
|
138
|
+
ctx.lineWidth = 1.8 + reliefSeed * 4.8;
|
|
138
139
|
ctx.beginPath();
|
|
139
140
|
ctx.moveTo(px, -depth);
|
|
140
|
-
ctx.bezierCurveTo(px - 10 -
|
|
141
|
+
ctx.bezierCurveTo(px - 10 - reliefSeed * 8, -24, px + 12 + reliefSeed * 6, 32, px - 4, depth);
|
|
141
142
|
ctx.stroke();
|
|
142
143
|
ctx.shadowBlur = 0;
|
|
143
144
|
}
|
|
@@ -15,6 +15,10 @@ function byId<T extends HTMLElement>(id: string): T | null {
|
|
|
15
15
|
return document.getElementById(id) as T | null;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
function uiText(ui: Ui, key: string, fallback = ''): string {
|
|
19
|
+
return ui[key] ?? fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
18
22
|
function isToolProfile(value: unknown): value is ToolProfile {
|
|
19
23
|
return typeof value === 'string' && PROFILES.includes(value as ToolProfile);
|
|
20
24
|
}
|
|
@@ -200,35 +204,35 @@ class ToolmarkView {
|
|
|
200
204
|
brightnessPercent: readNumber(this.brightnessInput, DEFAULTS.brightness),
|
|
201
205
|
gridEnabled: this.gridEnabled,
|
|
202
206
|
dark: isDarkTheme(),
|
|
203
|
-
reliefGraphLabel: this.ui
|
|
207
|
+
reliefGraphLabel: uiText(this.ui, 'reliefGraph'),
|
|
204
208
|
});
|
|
205
209
|
}
|
|
206
210
|
|
|
207
211
|
private updateLabels(result: ReturnType<StriationMatcher['compare']>): void {
|
|
208
212
|
const visualMode = this.hasUploadedImages();
|
|
209
|
-
this.setText('toolmark-correlation', visualMode ? this.ui
|
|
213
|
+
this.setText('toolmark-correlation', visualMode ? uiText(this.ui, 'visualMode') : `${result.correlation}%`);
|
|
210
214
|
this.setText('toolmark-verdict', this.verdictLabel(result.correlation, visualMode));
|
|
211
215
|
this.setText('toolmark-offset-label', this.offsetLabel(result));
|
|
212
|
-
this.setText('toolmark-rotation-label', `${result.rotationDegrees.toFixed(1)}${this.ui
|
|
216
|
+
this.setText('toolmark-rotation-label', `${result.rotationDegrees.toFixed(1)}${uiText(this.ui, 'degrees')}`);
|
|
213
217
|
this.setText('toolmark-zoom-label', `${readNumber(this.zoomInput, DEFAULTS.zoom)}%`);
|
|
214
|
-
this.setText('toolmark-interpretation', visualMode ? this.ui
|
|
218
|
+
this.setText('toolmark-interpretation', visualMode ? uiText(this.ui, 'visualInterpretation') : '');
|
|
215
219
|
this.setText('toolmark-phase-label', `${result.phaseScore}%`);
|
|
216
220
|
this.setText('toolmark-rotation-fit-label', `${result.rotationScore}%`);
|
|
217
|
-
this.setText('toolmark-known-name', this.knownSample?.name ?? this.ui
|
|
218
|
-
this.setText('toolmark-questioned-name', this.questionedSample?.name ?? this.ui
|
|
221
|
+
this.setText('toolmark-known-name', this.knownSample?.name ?? uiText(this.ui, 'noFile'));
|
|
222
|
+
this.setText('toolmark-questioned-name', this.questionedSample?.name ?? uiText(this.ui, 'noFile'));
|
|
219
223
|
this.updateMeters(result);
|
|
220
224
|
}
|
|
221
225
|
|
|
222
226
|
private verdictLabel(correlation: number, visualMode: boolean): string {
|
|
223
|
-
if (visualMode) return this.ui
|
|
224
|
-
if (correlation >= 82) return this.ui
|
|
225
|
-
if (correlation >= 58) return this.ui
|
|
226
|
-
return this.ui
|
|
227
|
+
if (visualMode) return uiText(this.ui, 'visualVerdict');
|
|
228
|
+
if (correlation >= 82) return uiText(this.ui, 'verdictStrong');
|
|
229
|
+
if (correlation >= 58) return uiText(this.ui, 'verdictPartial');
|
|
230
|
+
return uiText(this.ui, 'verdictWeak');
|
|
227
231
|
}
|
|
228
232
|
|
|
229
233
|
private offsetLabel(result: ReturnType<StriationMatcher['compare']>): string {
|
|
230
|
-
if (this.unitSystem === 'imperial') return `${result.offsetThousandths.toFixed(2)} ${this.ui
|
|
231
|
-
return `${result.offsetMicrons.toFixed(0)} ${this.ui
|
|
234
|
+
if (this.unitSystem === 'imperial') return `${result.offsetThousandths.toFixed(2)} ${uiText(this.ui, 'thousandths')}`;
|
|
235
|
+
return `${result.offsetMicrons.toFixed(0)} ${uiText(this.ui, 'microns')}`;
|
|
232
236
|
}
|
|
233
237
|
|
|
234
238
|
private updateMeters(result: ReturnType<StriationMatcher['compare']>): void {
|
|
@@ -275,17 +279,12 @@ class ToolmarkView {
|
|
|
275
279
|
private exportCanvas(): void {
|
|
276
280
|
if (!this.canvas) return;
|
|
277
281
|
const link = document.createElement('a');
|
|
278
|
-
link.download = this.ui.
|
|
282
|
+
link.download = uiText(this.ui, 'exportFilename', 'toolmark-comparison.png');
|
|
279
283
|
link.href = this.canvas.toDataURL('image/png');
|
|
280
284
|
link.click();
|
|
281
285
|
}
|
|
282
286
|
|
|
283
|
-
private offset(): number {
|
|
284
|
-
return readNumber(this.offsetInput, DEFAULTS.offset);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
private rotation(): number {
|
|
288
|
-
return readNumber(this.rotationInput, DEFAULTS.rotation);
|
|
289
|
-
}
|
|
287
|
+
private offset(): number { return readNumber(this.offsetInput, DEFAULTS.offset); }
|
|
290
288
|
|
|
289
|
+
private rotation(): number { return readNumber(this.rotationInput, DEFAULTS.rotation); }
|
|
291
290
|
}
|
|
@@ -74,7 +74,7 @@ const { ui } = Astro.props;
|
|
|
74
74
|
</div>
|
|
75
75
|
</section>
|
|
76
76
|
|
|
77
|
-
<script id="gsr-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
77
|
+
<script is:inline id="gsr-ui" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
78
78
|
<script>
|
|
79
79
|
import { GsrDispersionModel } from './logic';
|
|
80
80
|
import type { AmmoType, GsrParticle } from './logic';
|
|
@@ -113,7 +113,7 @@ function createParticles(config: ParticleFieldConfig): GsrParticle[] {
|
|
|
113
113
|
y: Math.sin(angle) * radial,
|
|
114
114
|
radius: isSoot ? 1.8 + random() * 4 : 0.9 + random() * 2.8,
|
|
115
115
|
opacity: Math.max(0.16, Math.min(0.92, (densityScore / 100) * (0.45 + random() * 0.65))),
|
|
116
|
-
element: isSoot ? 'soot' : elements[Math.floor(random() * 3)],
|
|
116
|
+
element: isSoot ? 'soot' : (elements[Math.floor(random() * 3)] ?? 'lead'),
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ScienceToolEntry, ToolLocaleContent } from '../../types';
|
|
2
2
|
import type { TimeOfDeathAlgorMortisUI } from './ui';
|
|
3
3
|
|
|
4
|
+
export type { TimeOfDeathAlgorMortisUI } from './ui';
|
|
5
|
+
|
|
4
6
|
export type TimeOfDeathAlgorMortisLocaleContent = ToolLocaleContent<TimeOfDeathAlgorMortisUI>;
|
|
5
7
|
|
|
6
8
|
export const timeOfDeathAlgorMortisCalculator: ScienceToolEntry<TimeOfDeathAlgorMortisUI> = {
|
|
@@ -163,7 +163,7 @@ const { ui } = Astro.props;
|
|
|
163
163
|
</main>
|
|
164
164
|
</div>
|
|
165
165
|
|
|
166
|
-
<script id="widmark-ui-data" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
166
|
+
<script is:inline id="widmark-ui-data" type="application/json" set:html={JSON.stringify(ui)}></script>
|
|
167
167
|
|
|
168
168
|
<script>
|
|
169
169
|
import { WidmarkEngine } from './logic';
|
|
@@ -154,6 +154,11 @@ export const content: ToolLocaleContent = {
|
|
|
154
154
|
type: 'paragraph',
|
|
155
155
|
html: 'Nach dem Eintritt in den Blutkreislauf wird Alkohol primär in der Leber durch das Enzym Alkoholdehydrogenase (ADH) abgebaut. Da dieses Enzym bereits bei sehr geringen Konzentrationen gesättigt ist, verläuft der Abbau nach einer Kinetik nullter Ordnung. Dies bedeutet, dass pro Zeiteinheit eine konstante Alkoholmenge eliminiert wird. Der forensisch etablierte Mittelwert (β<sub>60</sub>) beträgt 0,15 g/L pro Stunde, was dem Abbau von etwa 10 g reinem Alkohol pro Stunde entspricht. Dieser lineare Abbau erzeugt den geradlinigen Abfall der Kurve.',
|
|
156
156
|
},
|
|
157
|
+
{
|
|
158
|
+
type: 'paragraph',
|
|
159
|
+
html: 'Für eine Rückrechnung muss außerdem der Zeitpunkt der Messung eindeutig feststehen. Eine Schätzung zum Trinkende ist keine direkte Messung der Resorption: Der Blutalkohol kann nach dem letzten Getränk noch ansteigen, während sich der Magen entleert. Deshalb sollten Trinkmengen, Zeitpunkte, Körpergewicht, angenommener Verteilungsfaktor und Eliminationsrate getrennt dokumentiert werden. Die Anzeige eignet sich zum Vergleichen dieser Szenarien, nicht als alleinige Grundlage für eine rechtliche Entscheidung.',
|
|
160
|
+
},
|
|
161
|
+
{ type: 'paragraph', html: 'Alle Werte bleiben Näherungen und müssen mit ihren Annahmen dokumentiert werden.' },
|
|
157
162
|
|
|
158
163
|
{ type: 'paragraph', html: "Nutzen Sie das Ergebnis zur Planung und zum Szenarienvergleich; es ersetzt keine offizielle Berechnung oder Fachberatung." },
|
|
159
164
|
{ type: 'paragraph', html: "Deuten Sie das Ergebnis gemeinsam mit den angezeigten Annahmen, bevor Sie es verwenden." },
|
|
@@ -157,7 +157,8 @@ export const content: ToolLocaleContent = {
|
|
|
157
157
|
|
|
158
158
|
{ type: 'paragraph', html: "Utilisez le résultat pour planifier et comparer des scénarios ; il ne remplace ni un calcul officiel ni un avis professionnel." },
|
|
159
159
|
{ type: 'paragraph', html: "Interprétez le résultat avec les hypothèses affichées par le calculateur avant de l'utiliser." },
|
|
160
|
-
{ type: 'paragraph', html: "Vérifiez les données, unités, arrondi, date et juridiction, car chacun de ces éléments peut modifier l'estimation." },
|
|
160
|
+
{ type: 'paragraph', html: "Vérifiez les données, unités, arrondi, date et juridiction, car chacun de ces éléments peut modifier l'estimation." },
|
|
161
|
+
{ type: 'paragraph', html: "Pour une rétrogradation fiable, notez séparément l'heure du dernier verre, la durée d'absorption supposée, le poids, le facteur de distribution et le taux d'élimination. Une valeur calculée sert à comparer des scénarios et ne remplace pas une expertise médico-légale complète. L'absorption peut se poursuivre après le dernier verre et la mesure dépend de l'état d'hydratation, du contenu de l'estomac et de la cinétique retenue. Chaque hypothèse doit donc rester visible dans le rapport. Le résultat doit être présenté avec son incertitude et son contexte." },],
|
|
161
162
|
faq,
|
|
162
163
|
bibliography,
|
|
163
164
|
howTo,
|
|
@@ -154,6 +154,7 @@ export const content: ToolLocaleContent = {
|
|
|
154
154
|
type: 'paragraph',
|
|
155
155
|
html: 'Setelah masuk ke sirkulasi darah, alkohol dimetabolisme terutama di hati oleh enzim alkohol dehidrogenase (ADH). Enzim ini mengalami kejenuhan pada konsentrasi yang sangat rendah (0,02 g/L), sehingga metabolisme berlangsung dengan kecepatan konstan tanpa dipengaruhi kadar alkohol dalam darah. Rata-rata laju eliminasi forensik (β<sub>60</sub>) ditetapkan sebesar 0,15 g/L per jam. Penurunan konstan ini menghasilkan kemiringan linier lurus pada kurva hingga mencapai angka nol.',
|
|
156
156
|
},
|
|
157
|
+
{ type: 'paragraph', html: 'Untuk membaca simulasi dengan benar, pisahkan waktu konsumsi dari waktu pengukuran dan tuliskan semua asumsi tentang absorpsi, distribusi, hidrasi, dan eliminasi. Kadar yang dihitung adalah perkiraan matematis untuk membandingkan skenario. Keputusan resmi harus menggunakan catatan pemeriksaan, metode tervalidasi, dan penilaian ahli yang sesuai dengan yurisdiksi. Faktor tubuh, makanan, obat, kesehatan, dan ketidakpastian waktu dapat memengaruhi interpretasi. Tampilkan rentang dan asumsi secara terbuka agar hasil tidak disalahpahami sebagai ukuran langsung.' },
|
|
157
158
|
|
|
158
159
|
{ type: 'paragraph', html: "Gunakan hasil untuk perencanaan dan perbandingan skenario; hasil ini bukan pengganti perhitungan resmi atau nasihat ahli." },
|
|
159
160
|
{ type: 'paragraph', html: "Tafsirkan hasil bersama asumsi yang ditampilkan kalkulator sebelum menggunakannya." },
|
|
@@ -105,6 +105,8 @@ export const content: ToolLocaleContent = {
|
|
|
105
105
|
text: 'Tossicologia Forense e Cinetica dell\'Etanolo',
|
|
106
106
|
level: 2,
|
|
107
107
|
},
|
|
108
|
+
{ type: 'paragraph', html: "Il valore visualizzato dipende dal momento scelto e dai parametri inseriti. Conserva i dati originali, indica quali informazioni sono state stimate e confronta più scenari quando l'orario non è certo. Questo uso didattico rende chiaro il margine di errore e impedisce di leggere la curva come una prova isolata." },
|
|
109
|
+
{ type: 'paragraph', html: "Una stima trasparente distingue i dati osservati dalle ipotesi del modello. Documenta la sequenza temporale, la fase possibile di assorbimento e l'incertezza dell'eliminazione. Il grafico serve a confrontare scenari e non determina da solo responsabilità o conclusioni giudiziarie." },
|
|
108
110
|
{
|
|
109
111
|
type: 'paragraph',
|
|
110
112
|
html: 'La comprensione dei processi di <strong>assorbimento, distribuzione ed eliminazione dell\'etanolo</strong> è un requisito essenziale in tossicologia forense e nella ricostruzione degli incidenti stradali. In seguito all\'assunzione, l\'alcol scende lungo l\'esofago fino allo stomaco, dove ha luogo un primo, modesto assorbimento. Tuttavia, la parte preponderante dell\'assorbimento dell\'etanolo avviene nel duodeno e nell\'intestino tenue per via dell\'enorme area superficiale disponibile. Lo svuotamento gastrico rappresenta il passaggio limitante, spiegando perché i pasti rallentino vistosamente la curva alcolemica.',
|
|
@@ -157,7 +159,8 @@ export const content: ToolLocaleContent = {
|
|
|
157
159
|
|
|
158
160
|
{ type: 'paragraph', html: "Usa il risultato per pianificare e confrontare scenari; non sostituisce un calcolo ufficiale o una consulenza professionale." },
|
|
159
161
|
{ type: 'paragraph', html: "Interpreta il risultato insieme alle ipotesi mostrate dal calcolatore prima di utilizzarlo." },
|
|
160
|
-
{ type: 'paragraph', html: "Controlla dati, unità, arrotondamento, data e giurisdizione, perché ciascun elemento può cambiare la stima." },
|
|
162
|
+
{ type: 'paragraph', html: "Controlla dati, unità, arrotondamento, data e giurisdizione, perché ciascun elemento può cambiare la stima." },
|
|
163
|
+
{ type: 'paragraph', html: "Per interpretare una retrostima documenta separatamente l'ora dell'ultimo drink, l'assorbimento ipotizzato, il peso, il fattore di distribuzione e la velocità di eliminazione. L'assorbimento può continuare dopo l'ultima bevanda e la disidratazione o il contenuto gastrico possono cambiare la curva. Il risultato è un confronto matematico tra scenari, non una misura diretta né un parere forense conclusivo." },],
|
|
161
164
|
faq,
|
|
162
165
|
bibliography,
|
|
163
166
|
howTo,
|