Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 38 additions & 21 deletions lifeloss/lifeloss.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,46 +37,58 @@ type LifeLossProcess interface {

// Init in the lifeloss package creates a life loss engine with the default settings
func Init(seed int64, warningSystem warning.WarningResponseSystem) LifeLossEngine {
//initialize the default high lethality rate relationship
var HighPD paireddata.PairedData
json.Unmarshal(DefaultHighLethalityBytes, &HighPD)
//initialize the default low lethality rate relationships
var LowPD paireddata.PairedData
json.Unmarshal(DefaultLowLethalityBytes, &LowPD)
//create a lethality curve instance for High Lethality
High := LethalityCurve{data: HighPD}
//create a lethality curve instance for Low Lethality
Low := LethalityCurve{data: LowPD}
//create a map of lethality zone to lethality curve
lethalityCurves := make(map[LethalityZone]LethalityCurve)
lethalityCurves[HighLethality] = High
lethalityCurves[LowLethality] = Low
//initalize the stability criteria
stabilityCriteria := make(map[string]StabilityCriteria)
stabilityCriteria["woodunanchored"] = RescDamWoodUnanchored
stabilityCriteria["woodanchored"] = RescDamWoodAnchored
stabilityCriteria["masonryconcretebrick"] = RescDamMasonryConcreteBrick
createLethalityCurve := func(data []byte) (LethalityCurve, error) {
var pd paireddata.PairedData
if err := json.Unmarshal(data, &pd); err != nil {
return LethalityCurve{}, err
}
return LethalityCurve{data: pd}, nil
}
high, err := createLethalityCurve(DefaultHighLethalityBytes)
if err != nil {
log.Fatalf("Failed to initialize high lethality curve: %v", err)
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Calling log.Fatalf will terminate the entire application on JSON errors. Consider changing Init to return an error so callers can handle initialization failures more gracefully.

Copilot uses AI. Check for mistakes.
}
low, err := createLethalityCurve(DefaultLowLethalityBytes)
if err != nil {
log.Fatalf("Failed to initialize low lethality curve: %v", err)
}
lethalityCurves := map[LethalityZone]LethalityCurve{
HighLethality: high,
LowLethality: low,
}
stabilityCriteria := map[string]StabilityCriteria{
WoodUnanchoredKey: RescDamWoodUnanchored,
WoodAnchoredKey: RescDamWoodAnchored,
MasonryConcreteBrickKey: RescDamMasonryConcreteBrick,
}
rng := rand.New(rand.NewSource(seed))

return LifeLossEngine{LethalityCurves: lethalityCurves, StabilityCriteria: stabilityCriteria, WarningSystem: warningSystem, SeedGenerator: rng}
return LifeLossEngine{
LethalityCurves: lethalityCurves,
StabilityCriteria: stabilityCriteria,
WarningSystem: warningSystem,
SeedGenerator: rng,
}
}

func LifeLossHeader() []string {
return []string{"ll_u65", "ll_o65", "ll_tot"} //@TODO: Consider adding structure stability state, fatality rates, and sampled hazard parameters
}

func LifeLossDefaultResults() []interface{} {
var ll_u65, ll_o65, ll_tot int32
ll_u65 = 0
ll_o65 = 0
ll_tot = 0
return []interface{}{ll_u65, ll_o65, ll_tot}
}

func (le LifeLossEngine) RedistributePopulation(e hazards.HazardEvent, s structures.StructureDeterministic) (structures.StructureDeterministic, error) {
remainingPop, _ := le.WarningSystem.WarningFunction()(s, e)
sout := s.Clone()
sout.PopulationSet = remainingPop
return sout, nil
}

func (le LifeLossEngine) EvaluateStabilityCriteria(e hazards.HazardEvent, s structures.StructureDeterministic) (Stability, error) {
if e.Has(hazards.DV) && e.Has(hazards.Depth) || e.Has(hazards.Velocity) && e.Has(hazards.Depth) {
sc, err := le.determineStability(s)
Expand Down Expand Up @@ -112,6 +124,7 @@ func (le LifeLossEngine) ComputeLifeLoss(e hazards.HazardEvent, s structures.Str
return le.submergenceCriteria(e, s, remainingPop, rng)
}
}

func applylethalityRateToPopulation(lethalityrate float64, population int32, rng *rand.Rand) int32 {
result := 0
for i := 0; i < int(population); i++ {
Expand All @@ -121,6 +134,7 @@ func applylethalityRateToPopulation(lethalityrate float64, population int32, rng
}
return int32(result)
}

func (lle LifeLossEngine) submergenceCriteria(e hazards.HazardEvent, s structures.StructureDeterministic, remainingPop structures.PopulationSet, rng *rand.Rand) (consequences.Result, error) {
//apply submergence criteria
//log.Println("Submergence Based Lifeloss")
Expand Down Expand Up @@ -195,6 +209,7 @@ func (lle LifeLossEngine) submergenceCriteria(e hazards.HazardEvent, s structure
return consequences.Result{Headers: header, Result: []interface{}{llu65, llo65, llu65 + llo65}}, nil
}
}

func (lle LifeLossEngine) createLifeLossSet(popset structures.PopulationSet, lethalityRate float64, rng *rand.Rand) structures.PopulationSet {
result := structures.PopulationSet{0, 0, 0, 0}
result.Pop2amo65 = lle.evaluateLifeLoss(popset.Pop2amo65, lethalityRate, rng)
Expand All @@ -204,6 +219,7 @@ func (lle LifeLossEngine) createLifeLossSet(popset structures.PopulationSet, let
//log.Println(result)
return result
}

func (lle LifeLossEngine) evaluateLifeLoss(populationRemaining int32, lethalityRate float64, rng *rand.Rand) int32 {
var result int32 = 0
var i int32 = 0
Expand All @@ -214,6 +230,7 @@ func (lle LifeLossEngine) evaluateLifeLoss(populationRemaining int32, lethalityR
}
return result
}

func evaluateMobility(s structures.PopulationSet, rng *rand.Rand) map[Mobility]structures.PopulationSet {
//determine based on age and disability
result := make(map[Mobility]structures.PopulationSet)
Expand Down