cry-vetzdravila 1.0.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 (84) hide show
  1. package/.claude/settings.local.json +17 -0
  2. package/CLAUDE.md +82 -0
  3. package/LICENSE.md +16 -0
  4. package/README.md +376 -0
  5. package/a.txt +1643 -0
  6. package/bun.lock +197 -0
  7. package/dist/atcvet/opisATCvetKode.d.ts +23 -0
  8. package/dist/atcvet/podatkiATCvetKode.d.ts +20 -0
  9. package/dist/atcvet/pomeniNivojevATCvet.d.ts +1 -0
  10. package/dist/atcvet/types/AtcvetFile.d.ts +19 -0
  11. package/dist/generated/AtcVet.d.ts +9 -0
  12. package/dist/generated/RegisterZdravil.d.ts +8 -0
  13. package/dist/generated/seznamZdravil.d.ts +8 -0
  14. package/dist/index.d.ts +244 -0
  15. package/dist/index.js +141786 -0
  16. package/dist/register/MIN_OCENA_PODOBNOSTI.d.ts +2 -0
  17. package/dist/register/helper/normalizirajNaziv.d.ts +176 -0
  18. package/dist/register/helper/oblikujRezultatIskanja.d.ts +8 -0
  19. package/dist/register/helper/oceniPodobnost.d.ts +37 -0
  20. package/dist/register/helper/poisciZivalskoVrsto.d.ts +33 -0
  21. package/dist/register/helper/razcleniNaziv.d.ts +2 -0
  22. package/dist/register/podobnaZdravilaPoATC.d.ts +16 -0
  23. package/dist/register/podobnaZdravilaPoUcinkovinah.d.ts +18 -0
  24. package/dist/register/registerZdravil.d.ts +9 -0
  25. package/dist/register/types/KarencaZdravila.d.ts +24 -0
  26. package/dist/register/types/PotUporabeZdravila.d.ts +21 -0
  27. package/dist/register/types/RazclembaZdravila.d.ts +9 -0
  28. package/dist/register/types/RegisterZdravil.d.ts +2 -0
  29. package/dist/register/types/UcinkovinaZdravila.d.ts +20 -0
  30. package/dist/register/types/Zdravilo.d.ts +65 -0
  31. package/dist/register/types/ZdraviloZUtemeljitvijo.d.ts +9 -0
  32. package/dist/register/types/ZivalskeVrste.d.ts +158 -0
  33. package/dist/register/uganiZdravilo.d.ts +43 -0
  34. package/dist/register/zdravilaZaAtcVetKodo.d.ts +8 -0
  35. package/dist/register/zdraviloJeVakcinaZa.d.ts +18 -0
  36. package/docs/vakcine.md +195 -0
  37. package/package.json +39 -0
  38. package/src/atcvet/CLAUDE.md +18 -0
  39. package/src/atcvet/downloadLatestAtcvetPdf.ts +107 -0
  40. package/src/atcvet/opisATCvetKode.ts +116 -0
  41. package/src/atcvet/parseAtcvetPdf.ts +215 -0
  42. package/src/atcvet/podatkiATCvetKode.ts +34 -0
  43. package/src/atcvet/pomeniNivojevATCvet.ts +8 -0
  44. package/src/atcvet/types/AtcvetFile.ts +22 -0
  45. package/src/generate.ts +111 -0
  46. package/src/generated/AtcVet.ts +56704 -0
  47. package/src/generated/seznamZdravil.ts +44833 -0
  48. package/src/importParseAndBuildAll.ts +97 -0
  49. package/src/index.ts +289 -0
  50. package/src/interactive.ts +428 -0
  51. package/src/register/CLAUDE.md +230 -0
  52. package/src/register/MIN_OCENA_PODOBNOSTI.ts +3 -0
  53. package/src/register/downloadRegister.ts +148 -0
  54. package/src/register/helper/analizaVakcin.ts +90 -0
  55. package/src/register/helper/checkVrste.ts +72 -0
  56. package/src/register/helper/hashString.ts +27 -0
  57. package/src/register/helper/normalizirajNaziv.ts +493 -0
  58. package/src/register/helper/oblikujRezultatIskanja.ts +15 -0
  59. package/src/register/helper/oceniPodobnost.ts +194 -0
  60. package/src/register/helper/poisciZivalskoVrsto.ts +100 -0
  61. package/src/register/helper/razcleniNaziv.ts +105 -0
  62. package/src/register/helper/testNormalizacije.ts +89 -0
  63. package/src/register/helper/testPodobnosti.ts +238 -0
  64. package/src/register/helper/testVakcin.ts +103 -0
  65. package/src/register/parseRegister.ts +464 -0
  66. package/src/register/podobnaZdravilaPoATC.ts +71 -0
  67. package/src/register/podobnaZdravilaPoUcinkovinah.ts +136 -0
  68. package/src/register/registerZdravil.ts +22 -0
  69. package/src/register/stats.ts +114 -0
  70. package/src/register/types/KarencaZdravila.ts +26 -0
  71. package/src/register/types/PotUporabeZdravila.ts +21 -0
  72. package/src/register/types/RazclembaZdravila.ts +10 -0
  73. package/src/register/types/RegisterRaw.ts +23 -0
  74. package/src/register/types/RegisterZdravil.ts +3 -0
  75. package/src/register/types/UcinkovinaZdravila.ts +21 -0
  76. package/src/register/types/Zdravilo.ts +84 -0
  77. package/src/register/types/ZdraviloZUtemeljitvijo.ts +11 -0
  78. package/src/register/types/ZivalskeVrste.ts +7 -0
  79. package/src/register/uganiZdravilo.ts +142 -0
  80. package/src/register/zdravilaZaAtcVetKodo.ts +28 -0
  81. package/src/register/zdraviloJeVakcinaZa.ts +202 -0
  82. package/src/test/testPodobnosti.test.ts +126 -0
  83. package/src/test/zdravila.json +38693 -0
  84. package/tsconfig.json +18 -0
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Prenos xlsx datoteke s seznamom veterinarskih zdravil iz JAZMP
3
+ *
4
+ * Funkcija poišče najnovejšo xlsx datoteko na spletni strani in jo prenese v mapo data.
5
+ */
6
+
7
+ const BASE_URL = "https://www.jazmp.si/veterinarska-zdravila/podatki-o-zdravilih/seznam-zdravil";
8
+ const HREF_PREFIX = "https://www.jazmp.si/fileadmin/datoteke/seznami/SRZV";
9
+ const DATA_DIR = "./data";
10
+
11
+ /**
12
+ * Iz HTML vsebine poišče vse href atribute, ki se začnejo z HREF_PREFIX
13
+ */
14
+ function findXlsxLinks(html: string): string[] {
15
+ const links: string[] = [];
16
+ // Poišči vse <a> elemente s href atributom
17
+ const hrefRegex = /href=["']([^"']*?)["']/gi;
18
+ let match;
19
+
20
+ while ((match = hrefRegex.exec(html)) !== null) {
21
+ const href = match[1];
22
+ if (href.startsWith(HREF_PREFIX) && href.endsWith(".xlsx")) {
23
+ links.push(href);
24
+ }
25
+ }
26
+
27
+ return links;
28
+ }
29
+
30
+ /**
31
+ * Iz URL-ja izlušči datum in ga pretvori v Date objekt
32
+ * Primer URL: https://www.jazmp.si/fileadmin/datoteke/seznami/SRZV/20-11-2025.xlsx
33
+ * Vrne: Date objekt za 20. november 2025
34
+ */
35
+ function extractDateFromUrl(url: string): Date | null {
36
+ const filename = url.split("/").pop();
37
+ if (!filename) return null;
38
+
39
+ // Format: DD-MM-YYYY.xlsx
40
+ const dateMatch = filename.match(/(\d{1,2})-(\d{1,2})-(\d{4})\.xlsx/);
41
+ if (!dateMatch) return null;
42
+
43
+ const [, day, month, year] = dateMatch;
44
+ return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
45
+ }
46
+
47
+ /**
48
+ * Poišče najnovejšo xlsx datoteko med podanimi linki
49
+ */
50
+ function findNewestLink(links: string[]): string | null {
51
+ if (links.length === 0) return null;
52
+
53
+ let newestLink = links[0];
54
+ let newestDate = extractDateFromUrl(links[0]);
55
+
56
+ for (const link of links) {
57
+ const date = extractDateFromUrl(link);
58
+ if (date && newestDate && date > newestDate) {
59
+ newestDate = date;
60
+ newestLink = link;
61
+ }
62
+ }
63
+
64
+ return newestLink;
65
+ }
66
+
67
+ /**
68
+ * Prenese xlsx datoteko in jo shrani v data mapo
69
+ */
70
+ async function downloadFile(url: string): Promise<string> {
71
+ const response = await fetch(url);
72
+ if (!response.ok) {
73
+ throw new Error(`Napaka pri prenosu datoteke: ${response.status} ${response.statusText}`);
74
+ }
75
+
76
+ const arrayBuffer = await response.arrayBuffer();
77
+ const buffer = Buffer.from(arrayBuffer);
78
+
79
+ // Shrani vedno kot register.xlsx
80
+ const filepath = `${DATA_DIR}/register.xlsx`;
81
+
82
+ await Bun.write(filepath, buffer);
83
+
84
+ return filepath;
85
+ }
86
+
87
+ /**
88
+ * Glavna funkcija - prenese najnovejšo xlsx datoteko s JAZMP spletne strani
89
+ */
90
+ export async function downloadRegister(): Promise<string> {
91
+ console.log("Pridobivam HTML iz JAZMP...");
92
+
93
+ // Prenesi HTML strani
94
+ const response = await fetch(BASE_URL);
95
+ if (!response.ok) {
96
+ throw new Error(`Napaka pri dostopu do spletne strani: ${response.status}`);
97
+ }
98
+ const html = await response.text();
99
+
100
+ // Poišči vse xlsx linke
101
+ console.log("Iščem xlsx povezave...");
102
+ const links = findXlsxLinks(html);
103
+
104
+ if (links.length === 0) {
105
+ throw new Error("Ni najdenih xlsx datotek na spletni strani");
106
+ }
107
+
108
+ console.log(`Najdenih ${links.length} xlsx datotek`);
109
+
110
+ // Poišči najnovejšo
111
+ const newestLink = findNewestLink(links);
112
+ if (!newestLink) {
113
+ throw new Error("Ni mogoče določiti najnovejše datoteke");
114
+ }
115
+
116
+ console.log(`Najnovejša datoteka: ${newestLink}`);
117
+
118
+ // Prenesi datoteko
119
+ console.log("Prenašam datoteko...");
120
+ const filepath = await downloadFile(newestLink);
121
+
122
+ console.log(`Datoteka uspešno prenesena: ${filepath}`);
123
+
124
+ return filepath;
125
+ }
126
+
127
+ /**
128
+ * Vrne pot do register.xlsx če obstaja
129
+ */
130
+ export async function getLatestLocalFile(): Promise<string | null> {
131
+ const filepath = `${DATA_DIR}/register.xlsx`;
132
+ const file = Bun.file(filepath);
133
+ if (await file.exists()) {
134
+ return filepath;
135
+ }
136
+ return null;
137
+ }
138
+
139
+ // Če se izvaja direktno
140
+ if (import.meta.main) {
141
+ try {
142
+ const filepath = await downloadRegister();
143
+ console.log(`\nUspeh! Datoteka shranjena: ${filepath}`);
144
+ } catch (error) {
145
+ console.error("Napaka:", error);
146
+ process.exit(1);
147
+ }
148
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Analiza vakcin v registru
3
+ */
4
+
5
+ import { parseRegister } from "../parseRegister";
6
+
7
+ const register = parseRegister("./data/register.xlsx");
8
+
9
+ // Poišči ATC kode za vakcine (začnejo z QI)
10
+ const vakcine = register.zdravila.filter((z) => z.atcKoda?.startsWith("QI"));
11
+
12
+ console.log("Skupno število vakcin:", vakcine.length);
13
+
14
+ // Razvrsti po ATC kodi
15
+ const poATC = new Map<string, typeof vakcine>();
16
+ for (const z of vakcine) {
17
+ const atc = z.atcKoda?.substring(0, 5) || "neznano";
18
+ if (!poATC.has(atc)) poATC.set(atc, []);
19
+ poATC.get(atc)!.push(z);
20
+ }
21
+
22
+ console.log("\nVakcine po ATC kodah:");
23
+ for (const [atc, zdravila] of [...poATC.entries()].sort()) {
24
+ console.log("");
25
+ console.log(atc + " (" + zdravila.length + " zdravil):");
26
+ for (const z of zdravila.slice(0, 3)) {
27
+ console.log(" -", z.ime.substring(0, 70));
28
+ }
29
+ if (zdravila.length > 3) console.log(" ... in še", zdravila.length - 3);
30
+ }
31
+
32
+ // Poišči vakcine proti steklini
33
+ console.log("\n\n=== VAKCINE PROTI STEKLINI ===");
34
+ const steklina = vakcine.filter((z) => {
35
+ const imeLower = z.ime.toLowerCase();
36
+ const ucinkovineLower = z.ucinkovine?.map((u) => u.ucinkovina.toLowerCase()).join(" ") || "";
37
+ return (
38
+ imeLower.includes("rabies") ||
39
+ imeLower.includes("stekl") ||
40
+ ucinkovineLower.includes("rabies") ||
41
+ ucinkovineLower.includes("stekl")
42
+ );
43
+ });
44
+ for (const z of steklina) {
45
+ console.log("-", z.ime);
46
+ console.log(" ATC:", z.atcKoda);
47
+ console.log(" Učinkovine:", z.ucinkovine?.map((u) => u.ucinkovina).join(", "));
48
+ }
49
+
50
+ // Poišči vakcine proti leptospirozi
51
+ console.log("\n\n=== VAKCINE PROTI LEPTOSPIROZI ===");
52
+ const leptospiroza = vakcine.filter((z) => {
53
+ const imeLower = z.ime.toLowerCase();
54
+ const ucinkovineLower = z.ucinkovine?.map((u) => u.ucinkovina.toLowerCase()).join(" ") || "";
55
+ return imeLower.includes("lept") || ucinkovineLower.includes("leptospir");
56
+ });
57
+ for (const z of leptospiroza) {
58
+ console.log("-", z.ime);
59
+ console.log(" ATC:", z.atcKoda);
60
+ }
61
+
62
+ // Poišči vakcine proti kužnim boleznim (pasja kuga, parvo, hepatitis)
63
+ console.log("\n\n=== VAKCINE PROTI KUŽNIM BOLEZNIM (psi) ===");
64
+ const kuzne = vakcine.filter((z) => {
65
+ const imeLower = z.ime.toLowerCase();
66
+ const ucinkovineLower = z.ucinkovine?.map((u) => u.ucinkovina.toLowerCase()).join(" ") || "";
67
+ return (
68
+ imeLower.includes("dhpp") ||
69
+ imeLower.includes("distemper") ||
70
+ ucinkovineLower.includes("pasje kuge") ||
71
+ ucinkovineLower.includes("parvo") ||
72
+ ucinkovineLower.includes("adenovirus")
73
+ );
74
+ });
75
+ for (const z of kuzne) {
76
+ console.log("-", z.ime);
77
+ console.log(" ATC:", z.atcKoda);
78
+ }
79
+
80
+ // Statistika ATC kod
81
+ console.log("\n\n=== LEGENDA ATC KOD ZA VAKCINE ===");
82
+ console.log("QI01 - Vakcine za ptice (perutnina)");
83
+ console.log("QI02 - Vakcine za govedo");
84
+ console.log("QI04 - Vakcine za ovce in koze");
85
+ console.log("QI05 - Vakcine za prašiče");
86
+ console.log("QI06 - Vakcine za konje");
87
+ console.log("QI07 - Vakcine za pse");
88
+ console.log("QI08 - Vakcine za mačke");
89
+ console.log("QI09 - Vakcine za več vrst");
90
+ console.log("QI20 - Druge vakcine");
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Preveri katere vrste iz karenc nimajo zadetka v _match
3
+ */
4
+
5
+ import { skupneEntitete } from "cry-klikvet-logic";
6
+ import { parseRegister } from "../parseRegister";
7
+
8
+ const ZivalskeVrste = skupneEntitete.vrsteZivali;
9
+
10
+ // Dodatni vzorci iz parseRegister
11
+ const DODATNI_VZORCI_VRST: [RegExp, string][] = [
12
+ [/krav|telic|molznic/i, "govedo"],
13
+ [/race|brojler|jarki|mladic|fazan|prepelic|jerebic/i, "perutnina"],
14
+ [/osl[ie]|ponij/i, "konji"],
15
+ [/postrv/i, "ribe"],
16
+ [/^mačke$/i, "mačke"],
17
+ ];
18
+
19
+ const register = parseRegister("./data/register.xlsx");
20
+
21
+ // Zberi vse unikatne vrste iz karenc
22
+ const vrsteVKarencah = new Set<string>();
23
+ for (const z of register.zdravila) {
24
+ for (const k of z.karence) {
25
+ vrsteVKarencah.add(String(k.vrsta).toLowerCase());
26
+ }
27
+ }
28
+
29
+ function findMatch(vrsta: string): { key: string; nadrejena: string | null } | null {
30
+ // 1. Poskusi z _match
31
+ for (const [key, vrstaDef] of Object.entries(ZivalskeVrste)) {
32
+ if (vrstaDef?._match?.test(vrsta)) {
33
+ const nadrejena = vrstaDef.vrsta !== key ? vrstaDef.vrsta : null;
34
+ return { key, nadrejena };
35
+ }
36
+ }
37
+
38
+ // 2. Poskusi z dodatnimi vzorci
39
+ for (const [pattern, nadrejena] of DODATNI_VZORCI_VRST) {
40
+ if (pattern.test(vrsta)) {
41
+ return { key: vrsta, nadrejena: vrsta !== nadrejena.toLowerCase() ? nadrejena : null };
42
+ }
43
+ }
44
+
45
+ return null;
46
+ }
47
+
48
+ console.log("=== VRSTE BREZ ZADETKA ===\n");
49
+
50
+ const brezZadetka: string[] = [];
51
+ for (const vrsta of vrsteVKarencah) {
52
+ const match = findMatch(vrsta);
53
+ if (!match) {
54
+ brezZadetka.push(vrsta);
55
+ console.log(`${vrsta} → NI ZADETKA`);
56
+ }
57
+ }
58
+
59
+ console.log("\n=== VRSTE Z ZADETKOM ===\n");
60
+
61
+ for (const vrsta of vrsteVKarencah) {
62
+ const match = findMatch(vrsta);
63
+ if (match) {
64
+ console.log(`${vrsta} → ${match.key}` + (match.nadrejena ? ` (nadrejena: ${match.nadrejena})` : ""));
65
+ }
66
+ }
67
+
68
+ console.log(`\n=== POVZETEK ===`);
69
+ console.log(`Vrst brez zadetka: ${brezZadetka.length}`);
70
+ if (brezZadetka.length > 0) {
71
+ console.log(`Manjkajoče: ${brezZadetka.join(", ")}`);
72
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Fast, high-specificity 32-bit hash (xxHash32-style avalanche) -> unsigned number
3
+ * If !text returns undefined
4
+ **/
5
+ export function hashString(text: string | undefined): number | undefined {
6
+
7
+ if (!text) return undefined;
8
+
9
+ let h = 0x9e3779b1 ^ text.length; // seed mixed with length
10
+
11
+ for (let i = 0; i < text.length; i++) {
12
+ h ^= text.charCodeAt(i);
13
+ // h *= 0x85ebca6b (done via Math.imul for 32-bit overflow semantics)
14
+ h = Math.imul(h, 0x85ebca6b);
15
+ // rotate left 13
16
+ h = (h << 13) | (h >>> 19);
17
+ }
18
+
19
+ // final avalanche (fmix32-like)
20
+ h ^= h >>> 16;
21
+ h = Math.imul(h, 0x7feb352d);
22
+ h ^= h >>> 15;
23
+ h = Math.imul(h, 0x846ca68b);
24
+ h ^= h >>> 16;
25
+
26
+ return h >>> 0; // 0 .. 4294967295
27
+ }