|
17 | 17 | #include <stdio.h> |
18 | 18 | #include <stdlib.h> |
19 | 19 | #include <ctype.h> |
| 20 | +#include <float.h> |
20 | 21 | #include <time.h> |
21 | 22 | #include <math.h> |
22 | 23 |
|
@@ -180,6 +181,44 @@ int parse_hex_field(const char **ptr, const char *key, uint8_t *out, size_t len) |
180 | 181 | return skip_symbol(ptr, '"'); |
181 | 182 | } |
182 | 183 |
|
| 184 | +int skip_key_value(const char **ptr, const char *key, const char *expected_value) { |
| 185 | + const char *p = *ptr; |
| 186 | + |
| 187 | + // Skip optional whitespace |
| 188 | + while (isspace((unsigned char)*p)) p++; |
| 189 | + |
| 190 | + // Match key |
| 191 | + size_t key_len = strlen(key); |
| 192 | + if (strncmp(p, "\"", 1) != 0) return 0; |
| 193 | + p++; |
| 194 | + |
| 195 | + if (strncmp(p, key, key_len) != 0) return 0; |
| 196 | + p += key_len; |
| 197 | + |
| 198 | + if (strncmp(p, "\"", 1) != 0) return 0; |
| 199 | + p++; |
| 200 | + |
| 201 | + // Skip colon and optional whitespace |
| 202 | + while (isspace((unsigned char)*p)) p++; |
| 203 | + if (*p != ':') return 0; |
| 204 | + p++; |
| 205 | + while (isspace((unsigned char)*p)) p++; |
| 206 | + |
| 207 | + // Match expected value |
| 208 | + size_t val_len = strlen(expected_value); |
| 209 | + if (strncmp(p, "\"", 1) != 0) return 0; |
| 210 | + p++; |
| 211 | + |
| 212 | + if (strncmp(p, expected_value, val_len) != 0) return 0; |
| 213 | + p += val_len; |
| 214 | + |
| 215 | + if (strncmp(p, "\"", 1) != 0) return 0; |
| 216 | + p++; |
| 217 | + |
| 218 | + *ptr = p; // Update pointer if match succeeded |
| 219 | + return 1; |
| 220 | +} |
| 221 | + |
183 | 222 | static bool parse_string_field(const char **ptr, const char *key, char *out, size_t max) { |
184 | 223 | if (!skip_key(ptr, key)) return false; |
185 | 224 | if (!skip_symbol(ptr, '"')) return false; |
@@ -612,31 +651,31 @@ const char* fossil_jellyfish_reason(fossil_jellyfish_chain *chain, const char *i |
612 | 651 | } |
613 | 652 |
|
614 | 653 | void fossil_jellyfish_decay_confidence(fossil_jellyfish_chain *chain, float decay_rate) { |
615 | | - if (!chain || chain->count == 0) return; |
| 654 | + if (!chain || chain->count == 0 || decay_rate <= 0.0f) return; |
616 | 655 |
|
617 | 656 | const float MIN_CONFIDENCE = 0.05f; |
618 | 657 | const float MAX_CONFIDENCE = 1.0f; |
619 | 658 |
|
620 | | - // Half-life of confidence in seconds (e.g. 24 hours = 86400s) |
621 | | - const double HALF_LIFE_SECONDS = 86400.0; |
| 659 | + // decay_rate here represents the half-life in seconds |
| 660 | + // To avoid too small or too large half-life, clamp decay_rate reasonably |
| 661 | + double half_life_seconds = fmax(1.0, (double)decay_rate); |
622 | 662 |
|
623 | | - // Current time in seconds |
624 | 663 | time_t now = time(NULL); |
625 | 664 |
|
626 | 665 | for (size_t i = 0; i < chain->count; ++i) { |
627 | 666 | fossil_jellyfish_block *block = &chain->memory[i]; |
628 | 667 | if (!block->valid) continue; |
629 | 668 |
|
630 | | - // Convert timestamps to seconds |
631 | | - time_t block_time = (time_t)(block->timestamp / 1000); // assuming ms |
| 669 | + time_t block_time = (time_t)(block->timestamp / 1000); |
632 | 670 | time_t age_seconds = now - block_time; |
633 | | - if (age_seconds <= 0) continue; // future or zero-age blocks aren't decayed |
634 | 671 |
|
635 | | - // Compute decay factor: confidence *= 0.5^(age / half-life) |
636 | | - double decay_factor = pow(0.5, (double)age_seconds / HALF_LIFE_SECONDS); |
| 672 | + if (age_seconds <= 0) continue; |
| 673 | + |
| 674 | + // Compute decay factor: |
| 675 | + // confidence *= 0.5 ^ (age / half_life) |
| 676 | + double decay_factor = pow(0.5, (double)age_seconds / half_life_seconds); |
637 | 677 | block->confidence *= (float)decay_factor; |
638 | 678 |
|
639 | | - // Clamp and check |
640 | 679 | block->confidence = fmaxf(0.0f, fminf(block->confidence, MAX_CONFIDENCE)); |
641 | 680 | if (block->confidence < MIN_CONFIDENCE) { |
642 | 681 | block->valid = 0; |
|
0 commit comments