hyf

Context-aware query service for Radroots
git clone https://radroots.dev/git/hyf.git
Log | Files | Refs | README | LICENSE

candidates.mojo (2881B)


      1 from std.collections import List
      2 
      3 
      4 @fieldwise_init
      5 struct Candidate(Copyable, Movable):
      6     var kind: String
      7     var text: String
      8     var start: Int
      9     var end: Int
     10 
     11 
     12 def _is_digit_byte(byte: UInt8) -> Bool:
     13     return byte >= UInt8(ord("0")) and byte <= UInt8(ord("9"))
     14 
     15 
     16 def _backward_number_start(text: String, unit_start: Int) -> Int:
     17     var bytes = text.as_bytes()
     18     var index = unit_start - 1
     19     while index >= 0:
     20         var byte = bytes[index]
     21         if byte == UInt8(ord(" ")) or byte == UInt8(ord("\t")):
     22             index -= 1
     23             continue
     24         break
     25     var end = index
     26     while index >= 0 and _is_digit_byte(bytes[index]):
     27         index -= 1
     28     if index == end:
     29         return -1
     30     return index + 1
     31 
     32 
     33 def discover_candidates(
     34     text: String,
     35     known_products: List[String],
     36     known_units: List[String],
     37     known_dates: List[String],
     38 ) -> List[Candidate]:
     39     var candidates = List[Candidate]()
     40     var lowered = text.lower()
     41 
     42     for product in known_products:
     43         if product.strip() == "":
     44             continue
     45         var index = lowered.find(product.lower())
     46         if index >= 0:
     47             candidates.append(
     48                 Candidate(
     49                     kind="product",
     50                     text=String(product),
     51                     start=index,
     52                     end=index + product.byte_length(),
     53                 )
     54             )
     55 
     56     for unit in known_units:
     57         if unit.strip() == "":
     58             continue
     59         var index = lowered.find(unit.lower())
     60         if index >= 0:
     61             var number_start = _backward_number_start(text, index)
     62             if number_start >= 0:
     63                 candidates.append(
     64                     Candidate(
     65                         kind="quantity",
     66                         text=String(
     67                             text[
     68                                 byte = number_start : index + unit.byte_length()
     69                             ]
     70                         ),
     71                         start=number_start,
     72                         end=index + unit.byte_length(),
     73                     )
     74                 )
     75 
     76     for date_word in known_dates:
     77         if date_word.strip() == "":
     78             continue
     79         var index = lowered.find(date_word.lower())
     80         if index >= 0:
     81             candidates.append(
     82                 Candidate(
     83                     kind="date",
     84                     text=String(date_word),
     85                     start=index,
     86                     end=index + date_word.byte_length(),
     87                 )
     88             )
     89     return candidates^
     90 
     91 
     92 def candidate_kinds(candidates: List[Candidate]) -> List[String]:
     93     var kinds = List[String]()
     94     for candidate in candidates:
     95         var seen = False
     96         for kind in kinds:
     97             if kind == candidate.kind:
     98                 seen = True
     99         if not seen:
    100             kinds.append(String(candidate.kind))
    101     return kinds^