# Common Herb Legislation System
#
# Models the legislative process from Common Herb:
# - Office holders propose tax bills
# - Elected officials vote based on ideology
# - Bills pass by majority
# - Passed bills change tax rates
#
# This file extends common_herb_politics.herb and connects to
# common_herb_economy.herb via the tax_rate relation.
#
# Key HERB features demonstrated:
# - Reified bills as entities
# - Aggregation for vote counting
# - Guards for eligibility
# - FUNCTIONAL relations for rate updates

# =============================================================================
# FUNCTIONAL DECLARATIONS
# =============================================================================

FUNCTIONAL tax_rate         # Current tax rate for a jurisdiction
FUNCTIONAL office_holder    # Who holds an office (single person)

# =============================================================================
# JURISDICTIONS
# =============================================================================

FACT gulpin is_a jurisdiction
FACT gulpin name "Gulpin"
FACT gulpin tax_rate 10

FACT northvale is_a jurisdiction
FACT northvale name "Northvale"
FACT northvale tax_rate 5

# =============================================================================
# OFFICES AND HOLDERS
# =============================================================================
# Each jurisdiction has a mayor and a council (legislative body)

FACT gulpin_mayor is_a office
FACT gulpin_mayor jurisdiction gulpin
FACT gulpin_mayor title "Mayor"
FACT gulpin_mayor can_propose_bills true

FACT gulpin_council is_a office
FACT gulpin_council jurisdiction gulpin
FACT gulpin_council title "Council"
FACT gulpin_council is_legislative true

# Current office holders (would be set by election system)
FACT gulpin_mayor office_holder bob
FACT bob holds_office gulpin_mayor

# Council members (simplified: 3 seats, all held)
FACT council_seat_1 is_a office
FACT council_seat_1 jurisdiction gulpin
FACT council_seat_1 member_of gulpin_council
FACT council_seat_1 office_holder alice
FACT alice holds_office council_seat_1

FACT council_seat_2 is_a office
FACT council_seat_2 jurisdiction gulpin
FACT council_seat_2 member_of gulpin_council
FACT council_seat_2 office_holder carol
FACT carol holds_office council_seat_2

FACT council_seat_3 is_a office
FACT council_seat_3 jurisdiction gulpin
FACT council_seat_3 member_of gulpin_council
FACT council_seat_3 office_holder dan
FACT dan holds_office council_seat_3

# =============================================================================
# CITIZENS WITH IDEOLOGY
# =============================================================================
# ideology_tax: -1 = wants low taxes, +1 = wants high taxes

FACT alice is_a citizen
FACT alice name "Alice"
FACT alice ideology_tax -0.5

FACT bob is_a citizen
FACT bob name "Bob"
FACT bob ideology_tax 0.7

FACT carol is_a citizen
FACT carol name "Carol"
FACT carol ideology_tax 0.3

FACT dan is_a citizen
FACT dan name "Dan"
FACT dan ideology_tax -0.2

# =============================================================================
# TAX BILLS (Reified)
# =============================================================================
# A bill is an entity with:
# - proposer: who proposed it
# - target_jurisdiction: which jurisdiction it affects
# - proposed_rate: the new tax rate
# - status: proposed | voting | passed | failed

# Bill 1: Bob proposes raising taxes (will fail - only Carol supports)
FACT bill_1 is_a tax_bill
FACT bill_1 proposer bob
FACT bill_1 target_jurisdiction gulpin
FACT bill_1 proposed_rate 15
FACT bill_1 status proposed

# Bill 2: Bob proposes lowering taxes (will pass - Alice and Dan support)
FACT bill_2 is_a tax_bill
FACT bill_2 proposer bob
FACT bill_2 target_jurisdiction gulpin
FACT bill_2 proposed_rate 5
FACT bill_2 status proposed

# =============================================================================
# RULES
# =============================================================================

# -----------------------------------------------------------------------------
# Rule: Validate bill proposer
# Only office holders with can_propose_bills can propose
# If valid, move bill to voting status
# -----------------------------------------------------------------------------
RULE validate_bill_proposer
  WHEN ?bill is_a tax_bill
  AND ?bill status proposed
  AND ?bill proposer ?p
  AND ?p holds_office ?office
  AND ?office can_propose_bills true
  THEN ?bill status voting
  RETRACT ?bill status proposed

# -----------------------------------------------------------------------------
# Rule: Council members evaluate bill based on ideology alignment
# High ideology_tax (+1) supports rate increases
# Low ideology_tax (-1) opposes rate increases
#
# Vote logic:
# - If proposed > current: support if ideology_tax > 0
# - If proposed < current: support if ideology_tax < 0
# - If proposed == current: abstain (no vote)
#
# We compute: (proposed - current) * ideology_tax > 0 means aligned
# If aligned, vote FOR. Otherwise vote AGAINST.
# -----------------------------------------------------------------------------
RULE council_vote_for
  WHEN ?bill is_a tax_bill
  AND ?bill status voting
  AND ?bill target_jurisdiction ?j
  AND ?bill proposed_rate ?proposed
  AND ?j tax_rate ?current
  AND ?seat member_of ?council
  AND ?council jurisdiction ?j
  AND ?council is_legislative true
  AND ?seat office_holder ?official
  AND ?official ideology_tax ?ideo
  IF (> (* (- ?proposed ?current) ?ideo) 0)
  THEN ?official votes_for ?bill

RULE council_vote_against
  WHEN ?bill is_a tax_bill
  AND ?bill status voting
  AND ?bill target_jurisdiction ?j
  AND ?bill proposed_rate ?proposed
  AND ?j tax_rate ?current
  AND ?seat member_of ?council
  AND ?council jurisdiction ?j
  AND ?council is_legislative true
  AND ?seat office_holder ?official
  AND ?official ideology_tax ?ideo
  IF (< (* (- ?proposed ?current) ?ideo) 0)
  THEN ?official votes_against ?bill

# Abstain when rate change is 0 (no vote cast either way)
# We could track this but it doesn't affect the outcome

# -----------------------------------------------------------------------------
# Rule: Count votes for each bill
# -----------------------------------------------------------------------------
RULE count_bill_votes_for
  WHEN ?bill is_a tax_bill
  AND ?bill status voting
  THEN ?bill total_for (count WHERE ?p votes_for ?bill)

RULE count_bill_votes_against
  WHEN ?bill is_a tax_bill
  AND ?bill status voting
  THEN ?bill total_against (count WHERE ?p votes_against ?bill)

# -----------------------------------------------------------------------------
# Rule: Determine bill outcome
# Majority wins. Ties fail (need strict majority to pass).
# -----------------------------------------------------------------------------
RULE bill_passes
  WHEN ?bill is_a tax_bill
  AND ?bill status voting
  AND ?bill total_for ?for
  AND ?bill total_against ?against
  IF (> ?for ?against)
  THEN ?bill outcome passed
  AND ?bill status decided
  RETRACT ?bill status voting

RULE bill_fails
  WHEN ?bill is_a tax_bill
  AND ?bill status voting
  AND ?bill total_for ?for
  AND ?bill total_against ?against
  IF (<= ?for ?against)
  THEN ?bill outcome failed
  AND ?bill status decided
  RETRACT ?bill status voting

# -----------------------------------------------------------------------------
# Rule: Apply passed bill to tax rate
# Uses FUNCTIONAL tax_rate so old value auto-retracts
# -----------------------------------------------------------------------------
RULE apply_tax_bill
  WHEN ?bill is_a tax_bill
  AND ?bill outcome passed
  AND ?bill target_jurisdiction ?j
  AND ?bill proposed_rate ?new_rate
  THEN ?j tax_rate ?new_rate
  AND ?bill applied true

