hyf

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

plan.mojo (3421B)


      1 from std.collections import List
      2 
      3 
      4 @fieldwise_init
      5 struct Allocation(Copyable, Movable):
      6     var lot_id: String
      7     var revision: String
      8     var line_id: String
      9     var value: Int
     10     var scale: Int
     11 
     12 
     13 @fieldwise_init
     14 struct LotCapacity(Copyable, Movable):
     15     var lot_id: String
     16     var revision: String
     17     var value: Int
     18     var scale: Int
     19 
     20 
     21 @fieldwise_init
     22 struct MatchPlan(Copyable, Movable):
     23     var plan_id: String
     24     var supplier_id: String
     25     var allocations: List[Allocation]
     26 
     27 
     28 def allocation(
     29     lot_id: String, revision: String, line_id: String, value: Int, scale: Int
     30 ) raises -> Allocation:
     31     if lot_id.strip() == "" or revision.strip() == "" or line_id.strip() == "":
     32         raise Error("allocation requires lot id, revision and line id")
     33     if value < 0:
     34         raise Error("allocation value must be non-negative")
     35     return Allocation(
     36         lot_id=String(lot_id),
     37         revision=String(revision),
     38         line_id=String(line_id),
     39         value=value,
     40         scale=scale,
     41     )
     42 
     43 
     44 def match_plan(
     45     plan_id: String, supplier_id: String, allocations: List[Allocation]
     46 ) raises -> MatchPlan:
     47     if plan_id.strip() == "" or supplier_id.strip() == "":
     48         raise Error("plan requires plan id and supplier id")
     49     var copied = List[Allocation]()
     50     for entry in allocations:
     51         copied.append(entry.copy())
     52     return MatchPlan(
     53         plan_id=String(plan_id),
     54         supplier_id=String(supplier_id),
     55         allocations=copied^,
     56     )
     57 
     58 
     59 def _rescale(value: Int, scale: Int, target: Int) -> Int:
     60     var result = value
     61     for _ in range(target - scale):
     62         result *= 10
     63     return result
     64 
     65 
     66 def plan_conservation_violations(
     67     plan: MatchPlan, lots: List[LotCapacity]
     68 ) raises -> List[String]:
     69     var violations = List[String]()
     70     var lot_keys = List[String]()
     71     var allocated = List[Int]()
     72     var allocated_scale = List[Int]()
     73     for entry in plan.allocations:
     74         var key = entry.lot_id + "@" + entry.revision
     75         var found = -1
     76         for index in range(len(lot_keys)):
     77             if lot_keys[index] == key:
     78                 found = index
     79         var scale = entry.scale
     80         var value = entry.value
     81         if found >= 0:
     82             if allocated_scale[found] > scale:
     83                 scale = allocated_scale[found]
     84             value = _rescale(value, entry.scale, scale) + _rescale(
     85                 allocated[found], allocated_scale[found], scale
     86             )
     87             allocated[found] = value
     88             allocated_scale[found] = scale
     89         else:
     90             lot_keys.append(String(key))
     91             allocated.append(value)
     92             allocated_scale.append(scale)
     93 
     94     for index in range(len(lot_keys)):
     95         var capacity_value = -1
     96         var capacity_scale = 0
     97         for lot in lots:
     98             if lot.lot_id + "@" + lot.revision == lot_keys[index]:
     99                 capacity_value = lot.value
    100                 capacity_scale = lot.scale
    101         var scale = (
    102             capacity_scale if capacity_scale
    103             > allocated_scale[index] else allocated_scale[index]
    104         )
    105         if capacity_value < 0:
    106             violations.append(lot_keys[index] + ": unknown capacity")
    107             continue
    108         if _rescale(allocated[index], allocated_scale[index], scale) > _rescale(
    109             capacity_value, capacity_scale, scale
    110         ):
    111             violations.append(lot_keys[index] + ": over-allocated")
    112     return violations^