| 473 | } |
| 474 | |
| 475 | RuleState GetState(TRuleSequences const & rules, time_t const timestamp) |
| 476 | { |
| 477 | RuleSequence const * emptyRule = nullptr; |
| 478 | RuleSequence const * dayMatchedRule = nullptr; |
| 479 | |
| 480 | for (auto it = rules.rbegin(); it != rules.rend(); ++it) |
| 481 | { |
| 482 | auto const & rule = *it; |
| 483 | auto const res = IsActiveImpl(rule, timestamp); |
| 484 | if (!res.first) |
| 485 | continue; |
| 486 | |
| 487 | bool const empty = rule.IsEmpty(); |
| 488 | if (res.second) |
| 489 | { |
| 490 | if (empty && !emptyRule) |
| 491 | emptyRule = &rule; |
| 492 | else |
| 493 | { |
| 494 | // Should understand if previous 'rule vs dayMatchedRule' should work |
| 495 | // like 'general x BUT specific y' or like 'x OR y'. |
| 496 | |
| 497 | if (dayMatchedRule && IsR1IncludesR2(rule, *dayMatchedRule)) |
| 498 | return RuleState::Closed; |
| 499 | |
| 500 | return ModifierToRuleState(rule.GetModifier()); |
| 501 | } |
| 502 | } |
| 503 | else if (!empty && !dayMatchedRule && ModifierToRuleState(rule.GetModifier()) == RuleState::Open) |
| 504 | { |
| 505 | // Save recent day-matched rule with Open state, but not time-matched. |
| 506 | dayMatchedRule = &rule; |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | if (emptyRule) |
| 511 | { |
| 512 | if (emptyRule->HasComment()) |
| 513 | return RuleState::Unknown; |
| 514 | else |
| 515 | return ModifierToRuleState(emptyRule->GetModifier()); |
| 516 | } |
| 517 | |
| 518 | return (rules.empty() |
| 519 | ? RuleState::Unknown |
| 520 | : RuleState::Closed); |
| 521 | } |
| 522 | } // namespace osmoh |